feat(firestore): support array functions#16128
Conversation
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request enhances the Firestore client library by integrating new array manipulation functions directly into pipeline expressions. This provides developers with more powerful and convenient ways to query and transform data within array fields, improving data processing capabilities without requiring client-side array handling. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request adds support for array_first, array_last, array_first_n, and array_last_n functions in Firestore pipelines. The implementation and system tests look good. However, I found issues in the unit tests for array_first_n and array_last_n where the parameter order is asserted incorrectly, leading to internally inconsistent tests. I've provided suggestions to fix these tests.
packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py
Outdated
Show resolved
Hide resolved
packages/google-cloud-firestore/tests/unit/v1/test_pipeline_expressions.py
Outdated
Show resolved
Hide resolved
…nit and system tests.
… array elements with optional index.
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request adds support for a number of new array functions in Firestore pipelines. The implementation looks mostly good, but there are a few areas for improvement.
There are some inconsistencies in the naming of the generated functions (e.g., maximum vs array_maximum) which should be standardized. The e2e tests for these functions are also missing assert_proto blocks to verify the generated output.
Additionally, there are some minor issues with docstrings and redundant code that can be cleaned up. The signature for array_transform is also a bit confusing and could be made clearer.
Overall, a solid addition with a few refinements needed.
packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py
Outdated
Show resolved
Hide resolved
packages/google-cloud-firestore/google/cloud/firestore_v1/pipeline_expressions.py
Outdated
Show resolved
Hide resolved
| def array_transform( | ||
| self, element_alias: str, body: "Expression", index_alias: str | None = None | ||
| ) -> "Expression": |
There was a problem hiding this comment.
The method signature for array_transform is (self, element_alias: str, body: "Expression", index_alias: str | None = None). However, the implementation and the expected backend protocol place the body argument last in the argument list sent to the backend. This discrepancy can be confusing and lead to incorrect usage.
To improve clarity and prevent misuse, consider making index_alias a keyword-only argument. This enforces that it's passed by name and makes the signature less ambiguous.
def array_transform(
self, element_alias: str, body: "Expression", *, index_alias: str | None = None
) -> "Expression":There was a problem hiding this comment.
This is probably a good suggestion
There was a problem hiding this comment.
This method is removed for the purpose of this PR because we are still waiting for reference implementation.
| if index_alias is not None: | ||
| args.append(self._cast_to_expr_or_convert_to_constant(index_alias)) | ||
|
|
||
| args.append(self._cast_to_expr_or_convert_to_constant(body)) |
There was a problem hiding this comment.
The body parameter is already typed as Expression. Calling _cast_to_expr_or_convert_to_constant on it is redundant, as unit tests suggest this function is a no-op for Expression instances. You can append body directly to the args list for clarity.
This also applies to array_filter on line 1733.
args.append(body)There was a problem hiding this comment.
irrelevant since this part is removed
| """ | ||
| Takes an array, evaluates a boolean expression on each element, and returns a new | ||
| array containing only the elements for which the expression evaluates to True. | ||
|
|
||
| Args: | ||
| element_alias: Element variable name. | ||
| body: Boolean expression applied to each element. | ||
|
|
||
| Returns: | ||
| Expression: The created FunctionExpression AST node. | ||
| """ |
There was a problem hiding this comment.
The docstring for array_filter is inconsistent with the other new functions in this PR.
- It's missing an
Example:section. - The
Returns:description is not as user-friendly as the others.
Please update it for consistency. For example:
"""
Takes an array and returns a new array containing only the elements for which
the given boolean expression evaluates to True.
Example:
>>> # Filter for numbers greater than 5
>>> Field.of("numbers").array_filter("num", Field.of("num").greater_than(5))
Args:
element_alias: Element variable name.
body: Boolean expression applied to each element.
Returns:
A new `Expression` representing the filtered array.
"""There was a problem hiding this comment.
irrelevant since this part is removed
| instance = Expression.array_maximum(arg1) | ||
| assert instance.name == "maximum" | ||
| assert instance.params == [arg1] | ||
| assert repr(instance) == "Value.maximum()" |
There was a problem hiding this comment.
this should be array_maximum. You can use infix_name_override for this
There was a problem hiding this comment.
Thanks, I have fixed array_maximum, array_maximum_n, array_minimum, array_minimum_n.
|
It looks like Gemini caught a typo and some other small suggestions. Other than that, LGTM |
Supports the following:
array_transform (need to check for ref impl when it's ready - docstring, and sep methods or not)array_filter (need to check for ref impl when it's ready - docstring, and sep methods or not)