From 11bdbccb9befaa871ee2f9f902fa279c86c4c250 Mon Sep 17 00:00:00 2001 From: Linchin Date: Thu, 5 Mar 2026 22:22:11 +0000 Subject: [PATCH 1/3] feat: Add `Rand` expression --- .../firestore_v1/pipeline_expressions.py | 11 +++++ .../tests/system/pipeline_e2e/math.yaml | 45 +++++++++++++++++++ .../unit/v1/test_pipeline_expressions.py | 6 +++ 3 files changed, 62 insertions(+) diff --git a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py index 376d785901fc..277fe18a83d3 100644 --- a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py +++ b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py @@ -2029,3 +2029,14 @@ class CurrentTimestamp(FunctionExpression): def __init__(self): super().__init__("current_timestamp", [], use_infix_repr=False) + + +class Rand(FunctionExpression): + """Creates an expression that returns a pseudorandom float between 0.0 (inclusive) and 1.0 (exclusive). + + Returns: + A new `Expression` representing the random value. + """ + + def __init__(self): + super().__init__("rand", [], use_infix_repr=False) diff --git a/packages/google-cloud-firestore/tests/system/pipeline_e2e/math.yaml b/packages/google-cloud-firestore/tests/system/pipeline_e2e/math.yaml index 4d35f746d3f4..0ef0a1f427d6 100644 --- a/packages/google-cloud-firestore/tests/system/pipeline_e2e/math.yaml +++ b/packages/google-cloud-firestore/tests/system/pipeline_e2e/math.yaml @@ -306,4 +306,49 @@ tests: - fieldReferenceValue: rating - integerValue: '2' name: mod + name: select + - description: testRand + pipeline: + - Collection: books + - Limit: 1 + - Select: + - AliasedExpression: + - And: + - FunctionExpression.greater_than_or_equal: + - Rand: [] + - Constant: 0.0 + - FunctionExpression.less_than: + - Rand: [] + - Constant: 1.0 + - "is_valid_rand" + assert_results: + - is_valid_rand: true + assert_proto: + pipeline: + stages: + - args: + - referenceValue: /books + name: collection + - args: + - integerValue: '1' + name: limit + - args: + - mapValue: + fields: + is_valid_rand: + functionValue: + name: and + args: + - functionValue: + name: greater_than_or_equal + args: + - functionValue: + name: rand + - doubleValue: 0.0 + - functionValue: + name: less_than + args: + - functionValue: + name: rand + - doubleValue: 1.0 name: select \ No newline at end of file diff --git a/packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py b/packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py index fe7beb460502..7b73de12099f 100644 --- a/packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py +++ b/packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py @@ -1583,3 +1583,9 @@ def test_maximum(self): assert repr(instance) == "Value.maximum()" infix_instance = arg1.maximum() assert infix_instance == instance + + def test_rand(self): + instance = expr.Rand() + assert instance.name == "rand" + assert instance.params == [] + assert repr(instance) == "Rand()" From 40a490b15450ebf6dda52a78677d2db937e4128e Mon Sep 17 00:00:00 2001 From: Linchin Date: Thu, 5 Mar 2026 22:33:20 +0000 Subject: [PATCH 2/3] feat: add trunc function expression --- .../firestore_v1/pipeline_expressions.py | 13 ++++ .../tests/system/pipeline_e2e/math.yaml | 63 +++++++++++++++++++ .../unit/v1/test_pipeline_expressions.py | 9 +++ 3 files changed, 85 insertions(+) diff --git a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py index 277fe18a83d3..7f4dda095de8 100644 --- a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py +++ b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py @@ -405,6 +405,19 @@ def sqrt(self) -> "Expression": """ return FunctionExpression("sqrt", [self]) + @expose_as_static + def trunc(self) -> "Expression": + """Creates an expression that truncates this expression towards zero. + + Example: + >>> # Truncate the 'value' field. + >>> Field.of("value").trunc() + + Returns: + A new `Expression` representing the truncated value. + """ + return FunctionExpression("trunc", [self]) + @expose_as_static def logical_maximum(self, *others: Expression | CONSTANT_TYPE) -> "Expression": """Creates an expression that returns the larger value between this expression diff --git a/packages/google-cloud-firestore/tests/system/pipeline_e2e/math.yaml b/packages/google-cloud-firestore/tests/system/pipeline_e2e/math.yaml index 0ef0a1f427d6..ca190a62d8e3 100644 --- a/packages/google-cloud-firestore/tests/system/pipeline_e2e/math.yaml +++ b/packages/google-cloud-firestore/tests/system/pipeline_e2e/math.yaml @@ -134,6 +134,69 @@ tests: - fieldReferenceValue: rating name: sqrt name: select + - description: testTrunc + pipeline: + - Collection: books + - Where: + - FunctionExpression.equal_any: + - Field: title + - - Constant: "To Kill a Mockingbird" # rating 4.2 + - Constant: "Pride and Prejudice" # rating 4.5 + - Constant: "The Lord of the Rings" # rating 4.7 + - Select: + - title + - AliasedExpression: + - FunctionExpression.trunc: + - Field: rating + - "trunc_rating" + - Sort: + - Ordering: + - Field: title + - ASCENDING + assert_results: + - title: "Pride and Prejudice" + trunc_rating: 4.0 + - title: "The Lord of the Rings" + trunc_rating: 4.0 + - title: "To Kill a Mockingbird" + trunc_rating: 4.0 + assert_proto: + pipeline: + stages: + - args: + - referenceValue: /books + name: collection + - args: + - functionValue: + args: + - fieldReferenceValue: title + - functionValue: + args: + - stringValue: "To Kill a Mockingbird" + - stringValue: "Pride and Prejudice" + - stringValue: "The Lord of the Rings" + name: array + name: equal_any + name: where + - args: + - mapValue: + fields: + title: + fieldReferenceValue: title + trunc_rating: + functionValue: + args: + - fieldReferenceValue: rating + name: trunc + name: select + - args: + - mapValue: + fields: + direction: + stringValue: ascending + expression: + fieldReferenceValue: title + name: sort - description: testRoundFunctionExpressionessions pipeline: - Collection: books diff --git a/packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py b/packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py index 7b73de12099f..3084fac965b1 100644 --- a/packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py +++ b/packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py @@ -1418,6 +1418,15 @@ def test_sqrt(self): infix_instance = arg1.sqrt() assert infix_instance == instance + def test_trunc(self): + arg1 = self._make_arg("Value") + instance = Expression.trunc(arg1) + assert instance.name == "trunc" + assert instance.params == [arg1] + assert repr(instance) == "Value.trunc()" + infix_instance = arg1.trunc() + assert infix_instance == instance + def test_array_length(self): arg1 = self._make_arg("Array") instance = Expression.array_length(arg1) From bc888161eef964e0382a4f2a712db316ae4e098b Mon Sep 17 00:00:00 2001 From: Linchin Date: Fri, 6 Mar 2026 18:43:22 +0000 Subject: [PATCH 3/3] update trunc docstring --- .../google/cloud/firestore_v1/pipeline_expressions.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py index 7f4dda095de8..9311d6d145fa 100644 --- a/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py +++ b/packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py @@ -407,11 +407,12 @@ def sqrt(self) -> "Expression": @expose_as_static def trunc(self) -> "Expression": - """Creates an expression that truncates this expression towards zero. + """Creates an expression that truncates a numeric value to the specified + number of decimal places. Example: - >>> # Truncate the 'value' field. - >>> Field.of("value").trunc() + >>> # Truncate the 'value' field to 2 decimal places. + >>> Field.of("value").trunc(2) Returns: A new `Expression` representing the truncated value. @@ -2045,10 +2046,10 @@ def __init__(self): class Rand(FunctionExpression): - """Creates an expression that returns a pseudorandom float between 0.0 (inclusive) and 1.0 (exclusive). + """Creates an expression that generates a random number between 0.0 and 1.0 but not including 1.0. Returns: - A new `Expression` representing the random value. + A new `Expression` representing the rand operation. """ def __init__(self):