|
12 | 12 | // See the License for the specific language governing permissions and
|
13 | 13 | // limitations under the License.
|
14 | 14 |
|
| 15 | +import Foundation |
| 16 | + |
| 17 | +/// |
| 18 | +/// A `BooleanExpression` is a specialized `FunctionExpression` that evaluates to a boolean value. |
| 19 | +/// |
| 20 | +/// It is used to construct conditional logic within Firestore pipelines, such as in `where` |
| 21 | +/// clauses or `cond` expressions. `BooleanExpression` instances can be combined using standard |
| 22 | +/// logical operators (`&&`, `||`, `!`, `^`) to create complex conditions. |
| 23 | +/// |
| 24 | +/// Example usage in a `where` clause: |
| 25 | +/// ```swift |
| 26 | +/// firestore.pipeline() |
| 27 | +/// .collection("products") |
| 28 | +/// .where( |
| 29 | +/// Field("price").greaterThan(100) && |
| 30 | +/// (Field("category").equal("electronics") || Field("on_sale").equal(true)) |
| 31 | +/// ) |
| 32 | +/// ``` |
15 | 33 | public class BooleanExpression: FunctionExpression, @unchecked Sendable {
|
16 | 34 | override public init(_ functionName: String, _ agrs: [Expression]) {
|
17 | 35 | super.init(functionName, agrs)
|
18 | 36 | }
|
19 | 37 |
|
| 38 | + /// Creates an aggregation that counts the number of documents for which this boolean expression |
| 39 | + /// evaluates to `true`. |
| 40 | + /// |
| 41 | + /// This is useful for counting documents that meet a specific condition without retrieving the |
| 42 | + /// documents themselves. |
| 43 | + /// |
| 44 | + /// ```swift |
| 45 | + /// // Count how many books were published after 1980 |
| 46 | + /// let post1980Condition = Field("published").greaterThan(1980) |
| 47 | + /// firestore.pipeline() |
| 48 | + /// .collection("books") |
| 49 | + /// .aggregate([ |
| 50 | + /// post1980Condition.countIf().as("modernBooksCount") |
| 51 | + /// ]) |
| 52 | + /// ``` |
| 53 | + /// |
| 54 | + /// - Returns: An `AggregateFunction` that performs the conditional count. |
20 | 55 | public func countIf() -> AggregateFunction {
|
21 | 56 | return AggregateFunction("count_if", [self])
|
22 | 57 | }
|
23 | 58 |
|
| 59 | + /// Creates a conditional expression that returns one of two specified expressions based on the |
| 60 | + /// result of this boolean expression. |
| 61 | + /// |
| 62 | + /// This is equivalent to a ternary operator (`condition ? then : else`). |
| 63 | + /// |
| 64 | + /// ```swift |
| 65 | + /// // Create a new field "status" based on the "rating" field. |
| 66 | + /// // If rating > 4.5, status is "top_rated", otherwise "regular". |
| 67 | + /// firestore.pipeline() |
| 68 | + /// .collection("products") |
| 69 | + /// .addFields([ |
| 70 | + /// Field("rating").greaterThan(4.5) |
| 71 | + /// .then(Constant("top_rated"), else: Constant("regular")) |
| 72 | + /// .as("status") |
| 73 | + /// ]) |
| 74 | + /// ``` |
| 75 | + /// |
| 76 | + /// - Parameters: |
| 77 | + /// - thenExpression: The `Expression` to evaluate if this boolean expression is `true`. |
| 78 | + /// - elseExpression: The `Expression` to evaluate if this boolean expression is `false`. |
| 79 | + /// - Returns: A new `FunctionExpression` representing the conditional logic. |
24 | 80 | public func then(_ thenExpression: Expression,
|
25 | 81 | else elseExpression: Expression) -> FunctionExpression {
|
26 | 82 | return FunctionExpression("cond", [self, thenExpression, elseExpression])
|
27 | 83 | }
|
28 | 84 |
|
| 85 | + /// Combines two boolean expressions with a logical AND (`&&`). |
| 86 | + /// |
| 87 | + /// The resulting expression is `true` only if both the left-hand side (`lhs`) and the right-hand |
| 88 | + /// side (`rhs`) are `true`. |
| 89 | + /// |
| 90 | + /// ```swift |
| 91 | + /// // Find books in the "Fantasy" genre with a rating greater than 4.5 |
| 92 | + /// firestore.pipeline() |
| 93 | + /// .collection("books") |
| 94 | + /// .where( |
| 95 | + /// Field("genre").equal("Fantasy") && Field("rating").greaterThan(4.5) |
| 96 | + /// ) |
| 97 | + /// ``` |
| 98 | + /// |
| 99 | + /// - Parameters: |
| 100 | + /// - lhs: The left-hand boolean expression. |
| 101 | + /// - rhs: The right-hand boolean expression. |
| 102 | + /// - Returns: A new `BooleanExpression` representing the logical AND. |
29 | 103 | public static func && (lhs: BooleanExpression,
|
30 | 104 | rhs: @autoclosure () throws -> BooleanExpression) rethrows
|
31 | 105 | -> BooleanExpression {
|
32 | 106 | try BooleanExpression("and", [lhs, rhs()])
|
33 | 107 | }
|
34 | 108 |
|
| 109 | + /// Combines two boolean expressions with a logical OR (`||`). |
| 110 | + /// |
| 111 | + /// The resulting expression is `true` if either the left-hand side (`lhs`) or the right-hand |
| 112 | + /// side (`rhs`) is `true`. |
| 113 | + /// |
| 114 | + /// ```swift |
| 115 | + /// // Find books that are either in the "Romance" genre or were published before 1900 |
| 116 | + /// firestore.pipeline() |
| 117 | + /// .collection("books") |
| 118 | + /// .where( |
| 119 | + /// Field("genre").equal("Romance") || Field("published").lessThan(1900) |
| 120 | + /// ) |
| 121 | + /// ``` |
| 122 | + /// |
| 123 | + /// - Parameters: |
| 124 | + /// - lhs: The left-hand boolean expression. |
| 125 | + /// - rhs: The right-hand boolean expression. |
| 126 | + /// - Returns: A new `BooleanExpression` representing the logical OR. |
35 | 127 | public static func || (lhs: BooleanExpression,
|
36 | 128 | rhs: @autoclosure () throws -> BooleanExpression) rethrows
|
37 | 129 | -> BooleanExpression {
|
38 | 130 | try BooleanExpression("or", [lhs, rhs()])
|
39 | 131 | }
|
40 | 132 |
|
| 133 | + /// Combines two boolean expressions with a logical XOR (`^`). |
| 134 | + /// |
| 135 | + /// The resulting expression is `true` if the left-hand side (`lhs`) and the right-hand side |
| 136 | + /// (`rhs`) have different boolean values. |
| 137 | + /// |
| 138 | + /// ```swift |
| 139 | + /// // Find books that are in the "Dystopian" genre OR have a rating of 5.0, but not both. |
| 140 | + /// firestore.pipeline() |
| 141 | + /// .collection("books") |
| 142 | + /// .where( |
| 143 | + /// Field("genre").equal("Dystopian") ^ Field("rating").equal(5.0) |
| 144 | + /// ) |
| 145 | + /// ``` |
| 146 | + /// |
| 147 | + /// - Parameters: |
| 148 | + /// - lhs: The left-hand boolean expression. |
| 149 | + /// - rhs: The right-hand boolean expression. |
| 150 | + /// - Returns: A new `BooleanExpression` representing the logical XOR. |
41 | 151 | public static func ^ (lhs: BooleanExpression,
|
42 | 152 | rhs: @autoclosure () throws -> BooleanExpression) rethrows
|
43 | 153 | -> BooleanExpression {
|
44 | 154 | try BooleanExpression("xor", [lhs, rhs()])
|
45 | 155 | }
|
46 | 156 |
|
| 157 | + /// Negates a boolean expression with a logical NOT (`!`). |
| 158 | + /// |
| 159 | + /// The resulting expression is `true` if the original expression is `false`, and vice versa. |
| 160 | + /// |
| 161 | + /// ```swift |
| 162 | + /// // Find books that are NOT in the "Science Fiction" genre |
| 163 | + /// firestore.pipeline() |
| 164 | + /// .collection("books") |
| 165 | + /// .where(!Field("genre").equal("Science Fiction")) |
| 166 | + /// ``` |
| 167 | + /// |
| 168 | + /// - Parameter lhs: The boolean expression to negate. |
| 169 | + /// - Returns: A new `BooleanExpression` representing the logical NOT. |
47 | 170 | public static prefix func ! (lhs: BooleanExpression) -> BooleanExpression {
|
48 | 171 | return BooleanExpression("not", [lhs])
|
49 | 172 | }
|
|
0 commit comments