Skip to content

Conversation

cherylEnkidu
Copy link
Contributor

No description provided.

Copy link
Contributor

Using Gemini Code Assist

The 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 in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and 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 to provide feedback.

@google-oss-bot
Copy link

1 Warning
⚠️ Did you forget to add a changelog entry? (Add #no-changelog to the PR description to silence this warning.)

Generated by 🚫 Danger

@wu-hui
Copy link
Contributor

wu-hui commented Sep 9, 2025

/gemini review

@wu-hui
Copy link
Contributor

wu-hui commented Sep 9, 2025

/gemini summary

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant and largely positive changes to the public Pipeline API. Key improvements include renaming Expr to Expression and its related types for better clarity, adopting more idiomatic Swift method names (e.g., greaterThan instead of gt), and consistently using arrays instead of variadic parameters for better API design. The documentation has also been substantially improved. I've identified a few minor areas for improvement, mainly around API convenience and documentation consistency.

Comment on lines 811 to +823
/// Creates an expression that concatenates this string expression with other string expressions.
/// Assumes `self` evaluates to a string.
/// Assumes `self` and all parameters evaluate to strings.
///
/// ```swift
/// // Combine 'part1', 'part2', and 'part3' fields
/// Field("part1").strConcat(Field("part2"), Field("part3"))
/// // Combine "firstName", "middleName", and "lastName" fields
/// Field("firstName").strConcat(Field("middleName"), Field("lastName"))
/// ```
///
/// - Parameter secondString: An `Expr` (evaluating to a string) to concatenate.
/// - Parameter otherStrings: Optional additional `Expr` (evaluating to strings) to concatenate.
/// - Returns: A new `FunctionExpr` representing the concatenated string.
func strConcat(_ secondString: Expr, _ otherStrings: Expr...) -> FunctionExpr

/// Creates an expression that concatenates this string expression with other string literals.
/// Assumes `self` evaluates to a string.
///
/// ```swift
/// // Combine 'firstName', " ", and 'lastName'
/// Field("firstName").strConcat(" ", "lastName")
/// ```
///
/// - Parameter secondString: A string literal to concatenate.
/// - Parameter otherStrings: Optional additional string literals to concatenate.
/// - Returns: A new `FunctionExpr` representing the concatenated string.
func strConcat(_ secondString: String, _ otherStrings: String...) -> FunctionExpr
/// - Parameter secondString: An `Expression` (evaluating to a string) to concatenate.
/// - Parameter otherStrings: Optional additional `Expression` (evaluating to strings) to
/// concatenate.
/// - Returns: A new `FunctionExpression` representing the concatenated string.
func strConcat(_ strings: [Expression]) -> FunctionExpression
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

The strConcat method has been updated to take an array of Expressions, which improves consistency. However, the previous convenience overload for string literals (_ secondString: String, _ otherStrings: String...) has been removed. This makes concatenating with literals more verbose (e.g., strConcat([Constant("a"), Constant("b")]) instead of strConcat("a", "b")). Please consider reintroducing an overload for String literals to improve developer experience. For example:

func strConcat(_ strings: String...) -> FunctionExpression

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussed. Not using variadic parameter in API due to its poor compatibility with array in Swift.

Comment on lines +382 to 385
public func aggregate(_ aggregates: [AliasedAggregate],
groups: [Selectable]? = nil) -> Pipeline {
return Pipeline(stages: stages + [Aggregate(accumulators: accumulator, groups: groups)], db: db)
}

/// Performs optionally grouped aggregation operations using field names for grouping.
///
/// Similar to the other `aggregate` method, but `groups` are specified as an array of `String`
/// field names.
///
/// ```swift
/// // let pipeline: Pipeline = ... // Assume pipeline from "books" collection.
/// // Count books for each publisher.
/// let groupedByPublisherPipeline = pipeline.aggregate(
/// [AggregateWithas(aggregate: countAll(), alias: "book_count")],
/// groups: ["publisher"] // Group by the "publisher" field name.
/// )
/// // let results = try await groupedByPublisherPipeline.execute()
/// // results.documents might be:
/// // [
/// // ["publisher": "Penguin", "book_count": 50],
/// // ["publisher": "HarperCollins", "book_count": 35]
/// // ]
/// ```
///
/// - Parameters:
/// - accumulator: An array of `AggregateWithAlias` expressions.
/// - groups: An optional array of `String` field names for grouping.
/// - Returns: A new `Pipeline` object with this stage appended.
public func aggregate(_ accumulator: [AggregateWithAlias],
groups: [String]? = nil) -> Pipeline {
let selectables = groups?.map { Field($0) }
return Pipeline(
stages: stages + [Aggregate(accumulators: accumulator, groups: selectables)],
db: db
)
return Pipeline(stages: stages + [Aggregate(accumulators: aggregates, groups: groups)], db: db)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

The aggregate method overload that accepted an array of Strings for grouping has been removed. This was a convenient API for simple grouping. Now, developers must explicitly create Field objects (e.g., groups: [Field("genre")] instead of groups: ["genre"]). Please consider adding this overload back for improved usability. A possible implementation could be:

public func aggregate(_ aggregates: [AliasedAggregate],
                      groups: [String]? = nil) -> Pipeline {
  let selectables = groups?.map { Field($0) }
  return self.aggregate(aggregates, groups: selectables)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for removing it is because if the optional field is omit, like the function only takes in first parameter, including overloads will make the call ambiguous since both overloads fulfill the syntax.

Comment on lines 557 to 558
/// - Parameter other: An array of at least one `Pipeline` whose documents will be unioned.
/// - Returns: A new `Pipeline` object with this stage appended.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

The documentation for union(with:) states that the other parameter is an array of Pipelines, but the function signature accepts a single Pipeline. Please correct the documentation to match the implementation.

Comment on lines 315 to 319
// TBD
// _ = db.pipeline().collection("books")
// .addFields(
// FieldPath.documentID()
// )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

This section is commented out with a "TBD" note. Please ensure this is either implemented or removed before merging.

Copy link
Contributor

Summary of Changes

This pull request introduces a significant refactoring of the public API for Firestore's pipeline feature, focusing on enhancing consistency, clarity, and Swift idiomatic usage. The changes streamline how expressions are built and how pipeline stages are configured, aiming to provide a more intuitive and predictable developer experience.

Highlights

  • API Renaming and Consistency: The core expression protocols and classes have been renamed for clarity and consistency. Expr is now Expression, FunctionExpr is FunctionExpression, BooleanExpr is BooleanExpression, ExprWithAlias is AliasedExpression, and AggregateWithAlias is AliasedAggregate. This provides a more idiomatic Swift experience.
  • Simplified Pipeline Stage Parameters: Many pipeline stage methods (addFields, removeFields, select, distinct, sort, aggregate) now consistently accept array parameters for multiple inputs, reducing the need for variadic arguments and improving readability.
  • Expression Method Signature Updates: Numerous extension methods on Expression (e.g., arithmetic, string, array, timestamp, bitwise operations) have been updated to align with the new naming conventions and improve parameter clarity (e.g., avg() is now average(), timestampAdd and substr use named parameters).
  • Removal of Redundant Classes: The Ascending and Descending classes have been removed, as sorting can now be expressed directly on Expression instances using ascending() and descending() methods. Similarly, the old DocumentId class and BooleanExpr class were replaced by new versions under the Expressions directory.
  • Xcode Project File Updates: The project.pbxproj file has been updated to correctly set lastKnownFileType for several C++ source files and to include a new GoogleService-Info.plist reference.
Changelog
  • Firestore/Example/Firestore.xcodeproj/project.pbxproj
    • Updated lastKnownFileType for several C++ source files.
    • Added reference to GoogleService-Info.plist.
  • Firestore/Swift/Source/ExprImpl.swift
    • Updated to use Expression, FunctionExpression, BooleanExpression, and AliasedExpression types.
    • Renamed avg() to average().
    • Changed internal function names for minimum() and maximum() to 'min' and 'max' respectively.
    • Changed internal function names for logicalMaximum() and logicalMinimum() to 'max' and 'min' respectively.
    • Updated timestampAdd and timestampSub parameter order and added named parameters.
    • Updated replaceFirst and replaceAll to use named with parameter.
    • Updated substr to use named position and length parameters.
  • Firestore/Swift/Source/Helper/PipelineHelper.swift
    • Updated sendableToExpr to return Expression.
    • Updated selectablesToMap to return [String: Expression].
    • Updated map and array functions to return FunctionExpression.
  • Firestore/Swift/Source/PipelineWrapper.swift
    • Updated SelectableWrapper protocol to use Expression for expr property.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Aggregation/AggregateFunction.swift
    • Updated args property to [Expression].
    • Renamed as method return type to AliasedAggregate.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Aggregation/AggregateWithAlias.swift
    • File renamed to Firestore/Swift/Source/SwiftAPI/Pipeline/Aggregation/AliasedAggregate.swift.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Aggregation/CountAll.swift
    • Added extensive documentation for CountAll class.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/ArrayContains.swift
    • Updated to inherit from BooleanExpression.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Ascending.swift
    • File removed.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Descending.swift
    • File removed.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/DistanceMeasure.swift
    • Changed static euclidean, cosine, and dotProduct properties from computed properties to let constants.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expr.swift
    • File renamed to Firestore/Swift/Source/SwiftAPI/Pipeline/Expression.swift.
    • Protocol Expr renamed to Expression.
    • Updated method signatures to use Expression, FunctionExpression, BooleanExpression, and AliasedExpression.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expr/ArrayExpression.swift
    • File renamed to Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/ArrayExpression.swift.
    • Updated to inherit from FunctionExpression and use Expression for internal arguments.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expr/Constant.swift
    • File renamed to Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Constant.swift.
    • Updated to conform to Expression.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expr/DocumentId.swift
    • File removed.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expr/Field.swift
    • File renamed to Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Field.swift.
    • Updated to conform to Expression and use Expression for expr property.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expr/FunctionExpr.swift
    • File renamed to Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpression.swift.
    • Updated to inherit from Expression and use Expression for internal arguments.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expr/FunctionExpr/BooleanExpr.swift
    • File removed.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expr/FunctionExpr/RandomExpr.swift
    • File renamed to Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/RandomExpression.swift.
    • Updated to inherit from FunctionExpression.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expr/MapExpression.swift
    • File renamed to Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/MapExpression.swift.
    • Updated to inherit from FunctionExpression and use Expression for internal arguments.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/ExprWithAlias.swift
    • File renamed to Firestore/Swift/Source/SwiftAPI/Pipeline/AliasedExpression.swift.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/DocumentId.swift
    • New file added, providing DocumentId class inheriting from Field.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/FunctionExpressions/BooleanExpression.swift
    • New file added, providing BooleanExpression class inheriting from FunctionExpression with logical operators.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Ordering.swift
    • Struct Ordering now uses Expression for expr property.
    • Static ascending and descending properties in Direction changed from computed properties to let constants.
  • Firestore/Swift/Source/SwiftAPI/Pipeline/Pipeline.swift
    • Updated addFields to take [Selectable].
    • Updated removeFields to take [Field] or [String].
    • Updated select to take [Selectable] or [String].
    • Updated where to take BooleanExpression.
    • Updated distinct to take [String] or [Selectable].
    • Updated aggregate to take [AliasedAggregate] and removed overload for [String] groups.
    • Updated findNearest to take VectorValue for vectorValue parameter.
    • Updated sort to take [Ordering].
    • Updated replace(with:) to take Expression.
    • Updated union(with:) to take a single Pipeline (documentation needs update).
    • Updated rawStage params from [Sendable?] to [Sendable].
  • Firestore/Swift/Source/SwiftAPI/Stages.swift
    • Updated Where stage to use BooleanExpression.
    • Updated AddFields stage to use [Selectable].
    • Updated Aggregate stage to use [AliasedAggregate] and [Expression] for groups.
    • Updated FindNearest stage to use VectorValue.
    • Updated ReplaceWith stage to use Expression.
    • Updated Unnest stage to use Expression for alias and field.
    • Updated RawStage params from [Sendable?] to [Sendable].
  • Firestore/Swift/Tests/Integration/PipelineApiTests.swift
    • Renamed test class from PipelineTests to PipelineApiTests.
    • Updated various test cases to reflect API changes (e.g., array parameters, new method names, new types).
  • Firestore/Swift/Tests/Integration/PipelineTests.swift
    • Updated various test cases to reflect API changes (e.g., array parameters, new method names, new types).
Activity
  • A warning was generated by the Danger bot indicating a missing changelog entry.
  • The author, wu-hui, requested a code review and a summary from Gemini Code Assist.

Copy link
Contributor

@wu-hui wu-hui left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved.

One thing to note: there will be more renames.

@wu-hui wu-hui assigned cherylEnkidu and unassigned wu-hui Sep 12, 2025
@cherylEnkidu cherylEnkidu merged commit 7c1bbd4 into cheryllin/ppl Sep 12, 2025
24 of 28 checks passed
@cherylEnkidu cherylEnkidu deleted the cheryllin/publicAPIchanges branch September 12, 2025 17:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants