feat(firestore): pipeline subqueries#14365
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces several enhancements to the Firestore Pipelines API, including support for subcollection pipelines, variable definitions via a new Define stage, and expressions for accessing fields (GetField) and variables (Variable). It also adds methods to convert pipelines into scalar or array expressions (ToScalarExpression, ToArrayExpression) and renames sampling functions for better clarity. The review feedback highlights a mismatch in a documentation example, suggests adhering to Go idiomatic error string and documentation comment conventions, and recommends removing a redundant top-level function to maintain API consistency.
6397d34 to
24ffae5
Compare
| return p | ||
| } | ||
| if other.c == nil { | ||
| p.err = fmt.Errorf("union only supports combining root pipelines; relative scope pipelines (like subcollection pipelines) are not supported") |
There was a problem hiding this comment.
One ergonomic factor to consider for the future: would users benefit from having these kind of errors exported for easier checking via errors.Is or similar?
) This PR introduces several refinements to the Firestore Pipelines experimental feature, aimed at improving API consistency, error reporting, and the reliability of integration tests. Key Changes: - API Refinement: - Renamed ArraySliceWithLength to ArraySliceToEnd to better reflect its behavior similar to [Java](https://github.com/googleapis/java-firestore/blob/9065134fd70da22250f038d7e964f26aebfeb3cf/google-cloud-firestore/src/main/java/com/google/cloud/firestore/pipeline/expressions/Expression.java#L2644). - Enabled the ArrayFilter expression (previously commented out). - Updated TimestampTruncateWithTimezone to accept any for the timezone parameter, allowing for dynamic timezone expressions. TimestampTruncateWithTimezone in Java accepts string or expression [src](https://github.com/googleapis/java-firestore/blob/9065134fd70da22250f038d7e964f26aebfeb3cf/google-cloud-firestore/src/main/java/com/google/cloud/firestore/pipeline/expressions/Expression.java#L3763-L3908). - Error Handling: - Introduced typed errors ErrPipelineWithoutDatabase and ErrUnionNotSupportRelativeScope to replace generic fmt.Errorf calls #14365 (comment). - Added internal nil checks across various pipeline stages (inputStageDocuments, findNearestStage, removeFieldsStage, etc.) to provide more descriptive error messages during proto conversion. - Integration Test Enhancements: - Replaced skipIfEnterprise with a more flexible skipIfEdition helper to handle feature support across different Firestore editions. - Improved resource cleanup in tests by moving t.Cleanup calls earlier, ensuring documents are deleted even if a test fails prematurely. - Updated deleteCollection to use Select().Documents(ctx) for more efficient document deletion during test setup/teardown. - Bug Fixes & Robustness: - Added nil checks when processing results in TestIntegration_Query_Pipeline. - Standardized test skipping logic across all pipeline-related integration tests.
Overview
This PR introduces support for pipeline subqueries, variable definitions, and joins in the Go Firestore SDK, achieving strict 1:1 feature parity with the Java SDK's pipeline APIs googleapis/java-firestore#2323.
Another reference PR: googleapis/google-cloud-python#16470
What are Subqueries?
In Firestore pipelines, subqueries allow you to embed an entire pipeline execution as a value within a single stage of an outer pipeline. This is incredibly powerful for performing complex "join-like" operations across different collections.
For example, while querying a restaurants collection, you can use a subquery to fetch, filter, and aggregate all documents from a nested reviews subcollection, and embed that aggregated result (e.g., average_rating) directly into the restaurant document being returned. Subqueries can be
evaluated into either an array of results (ToArrayExpression()) or a single scalar value (ToScalarExpression()).
Key Features & API Additions:
Type Safety & Defensive Constraints: