Skip to content

Commit 3dbece9

Browse files
authored
feat(firestore): Add array expressions (firebase#15900)
1 parent 7d7869f commit 3dbece9

File tree

4 files changed

+723
-29
lines changed

4 files changed

+723
-29
lines changed

Firestore/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
- [feature] Added support for `first`, `last`, `arrayAgg`, and `arrayAggDistinct` Pipeline expressions. (#15941)
33
- [feature] Added support for `trunc` and `rand` Pipeline expressions. (#15938)
44
- [changed] Minor refactor to avoid using an absl internal function. (#15889)
5+
- [feature] Added support for Pipeline expressions `arrayFirst`, `arrayFirstN`, `arrayLast`,
6+
`arrayLastN`, `arrayMinimumN`, `arrayMaximumN`, `arrayIndexOf`, `arrayLastIndexOf` and `arrayIndexOfAll`. (#15900)
57

68
# 12.10.0
79
- [feature] Added support for `regexFind` and `regexFindAll` Pipeline expressions.

Firestore/Swift/Source/ExpressionImplementation.swift

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,36 @@ public extension Expression {
563563
return FunctionExpression(functionName: "array_length", args: [self])
564564
}
565565

566+
func arrayFirst() -> FunctionExpression {
567+
return FunctionExpression(functionName: "array_first", args: [self])
568+
}
569+
570+
func arrayFirstN(_ n: Int) -> FunctionExpression {
571+
return FunctionExpression(
572+
functionName: "array_first_n",
573+
args: [self, Helper.sendableToExpr(n)]
574+
)
575+
}
576+
577+
func arrayFirstN(_ n: Expression) -> FunctionExpression {
578+
return FunctionExpression(functionName: "array_first_n", args: [self, n])
579+
}
580+
581+
func arrayLast() -> FunctionExpression {
582+
return FunctionExpression(functionName: "array_last", args: [self])
583+
}
584+
585+
func arrayLastN(_ n: Int) -> FunctionExpression {
586+
return FunctionExpression(
587+
functionName: "array_last_n",
588+
args: [self, Helper.sendableToExpr(n)]
589+
)
590+
}
591+
592+
func arrayLastN(_ n: Expression) -> FunctionExpression {
593+
return FunctionExpression(functionName: "array_last_n", args: [self, n])
594+
}
595+
566596
func arrayGet(_ offset: Int) -> FunctionExpression {
567597
return FunctionExpression(
568598
functionName: "array_get",
@@ -574,6 +604,42 @@ public extension Expression {
574604
return FunctionExpression(functionName: "array_get", args: [self, offsetExpression])
575605
}
576606

607+
func arrayIndexOf(_ value: Sendable) -> FunctionExpression {
608+
return FunctionExpression(
609+
functionName: "array_index_of",
610+
args: [self, Helper.sendableToExpr(value), Constant("first")]
611+
)
612+
}
613+
614+
func arrayIndexOf(_ value: Expression) -> FunctionExpression {
615+
return FunctionExpression(
616+
functionName: "array_index_of",
617+
args: [self, value, Constant("first")]
618+
)
619+
}
620+
621+
func arrayLastIndexOf(_ value: Sendable) -> FunctionExpression {
622+
return FunctionExpression(
623+
functionName: "array_index_of",
624+
args: [self, Helper.sendableToExpr(value), Constant("last")]
625+
)
626+
}
627+
628+
func arrayLastIndexOf(_ value: Expression) -> FunctionExpression {
629+
return FunctionExpression(functionName: "array_index_of", args: [self, value, Constant("last")])
630+
}
631+
632+
func arrayIndexOfAll(_ value: Sendable) -> FunctionExpression {
633+
return FunctionExpression(
634+
functionName: "array_index_of_all",
635+
args: [self, Helper.sendableToExpr(value)]
636+
)
637+
}
638+
639+
func arrayIndexOfAll(_ value: Expression) -> FunctionExpression {
640+
return FunctionExpression(functionName: "array_index_of_all", args: [self, value])
641+
}
642+
577643
func arrayMaximum() -> FunctionExpression {
578644
return FunctionExpression(functionName: "maximum", args: [self])
579645
}
@@ -582,6 +648,28 @@ public extension Expression {
582648
return FunctionExpression(functionName: "minimum", args: [self])
583649
}
584650

651+
func arrayMaximumN(_ n: Int) -> FunctionExpression {
652+
return FunctionExpression(
653+
functionName: "maximum_n",
654+
args: [self, Helper.sendableToExpr(n)]
655+
)
656+
}
657+
658+
func arrayMaximumN(_ n: Expression) -> FunctionExpression {
659+
return FunctionExpression(functionName: "maximum_n", args: [self, n])
660+
}
661+
662+
func arrayMinimumN(_ n: Int) -> FunctionExpression {
663+
return FunctionExpression(
664+
functionName: "minimum_n",
665+
args: [self, Helper.sendableToExpr(n)]
666+
)
667+
}
668+
669+
func arrayMinimumN(_ n: Expression) -> FunctionExpression {
670+
return FunctionExpression(functionName: "minimum_n", args: [self, n])
671+
}
672+
585673
func greaterThan(_ other: Expression) -> BooleanExpression {
586674
return BooleanFunctionExpression(functionName: "greater_than", args: [self, other])
587675
}

Firestore/Swift/Source/SwiftAPI/Pipeline/Expressions/Expression.swift

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,78 @@ public protocol Expression: Sendable {
471471
/// - Returns: A new `FunctionExpression` representing the length of the array.
472472
func arrayLength() -> FunctionExpression
473473

474+
/// Creates an expression that returns the first element of an array.
475+
/// Assumes `self` evaluates to an array.
476+
///
477+
/// ```swift
478+
/// // Get the first item in the "tags" array.
479+
/// Field("tags").arrayFirst()
480+
/// ```
481+
///
482+
/// - Returns: A new `FunctionExpression` representing the first element of the array.
483+
func arrayFirst() -> FunctionExpression
484+
485+
/// Creates an expression that returns the first `n` elements of an array.
486+
/// Assumes `self` evaluates to an array.
487+
///
488+
/// ```swift
489+
/// // Get the first 3 items in the "tags" array.
490+
/// Field("tags").arrayFirstN(3)
491+
/// ```
492+
///
493+
/// - Parameter n: The number of elements to return.
494+
/// - Returns: A new `FunctionExpression` representing the first `n` elements of the array.
495+
func arrayFirstN(_ n: Int) -> FunctionExpression
496+
497+
/// Creates an expression that returns the first `n` elements of an array.
498+
/// Assumes `self` evaluates to an array.
499+
///
500+
/// ```swift
501+
/// // Get the first n items in the "tags" array where n is specified by field "count".
502+
/// Field("tags").arrayFirstN(Field("count"))
503+
/// ```
504+
///
505+
/// - Parameter n: An `Expression` (evaluating to an Int) representing the number of elements to
506+
/// return.
507+
/// - Returns: A new `FunctionExpression` representing the first `n` elements of the array.
508+
func arrayFirstN(_ n: Expression) -> FunctionExpression
509+
510+
/// Creates an expression that returns the last element of an array.
511+
/// Assumes `self` evaluates to an array.
512+
///
513+
/// ```swift
514+
/// // Get the last item in the "tags" array.
515+
/// Field("tags").arrayLast()
516+
/// ```
517+
///
518+
/// - Returns: A new `FunctionExpression` representing the last element of the array.
519+
func arrayLast() -> FunctionExpression
520+
521+
/// Creates an expression that returns the last `n` elements of an array.
522+
/// Assumes `self` evaluates to an array.
523+
///
524+
/// ```swift
525+
/// // Get the last 3 items in the "tags" array.
526+
/// Field("tags").arrayLastN(3)
527+
/// ```
528+
///
529+
/// - Parameter n: The number of elements to return.
530+
/// - Returns: A new `FunctionExpression` representing the last `n` elements of the array.
531+
func arrayLastN(_ n: Int) -> FunctionExpression
532+
533+
/// Creates an expression that returns the last `n` elements of an array.
534+
/// Assumes `self` evaluates to an array.
535+
///
536+
/// ```swift
537+
/// // Get the last n items in the "tags" array where n is specified by field "count".
538+
/// Field("tags").arrayLastN(Field("count"))
539+
/// ```
540+
///
541+
/// - Parameter n: An `Expression` (evaluating to an Int) representing the number of elements to
542+
/// return.
543+
/// - Returns: A new `FunctionExpression` representing the last `n` elements of the array.
544+
func arrayLastN(_ n: Expression) -> FunctionExpression
545+
474546
/// Creates an expression that accesses an element in an array (from `self`) at the specified
475547
/// integer offset.
476548
/// A negative offset starts from the end. If the offset is out of bounds, an error may be
@@ -505,6 +577,84 @@ public protocol Expression: Sendable {
505577
/// - Returns: A new `FunctionExpression` representing the "arrayGet" operation.
506578
func arrayGet(_ offsetExpression: Expression) -> FunctionExpression
507579

580+
/// Creates an expression that returns the index of the first occurrence of a value in an array.
581+
/// Returns nil if the value is not found.
582+
/// Assumes `self` evaluates to an array.
583+
///
584+
/// ```swift
585+
/// // Get the index of "urgent" in the "tags" array.
586+
/// Field("tags").arrayIndexOf("urgent")
587+
/// ```
588+
///
589+
/// - Parameter value: The literal `Sendable` value to search for.
590+
/// - Returns: A new `FunctionExpression` representing the index of the value.
591+
func arrayIndexOf(_ value: Sendable) -> FunctionExpression
592+
593+
/// Creates an expression that returns the index of the first occurrence of a value in an array.
594+
/// Returns nil if the value is not found.
595+
/// Assumes `self` evaluates to an array.
596+
///
597+
/// ```swift
598+
/// // Get the index of the value of field "searchTag" in the "tags" array.
599+
/// Field("tags").arrayIndexOf(Field("searchTag"))
600+
/// ```
601+
///
602+
/// - Parameter value: An `Expression` representing the value to search for.
603+
/// - Returns: A new `FunctionExpression` representing the index of the value.
604+
func arrayIndexOf(_ value: Expression) -> FunctionExpression
605+
606+
/// Creates an expression that returns the index of the last occurrence of a value in an array.
607+
/// Returns nil if the value is not found.
608+
/// Assumes `self` evaluates to an array.
609+
///
610+
/// ```swift
611+
/// // Get the last index of "urgent" in the "tags" array.
612+
/// Field("tags").arrayLastIndexOf("urgent")
613+
/// ```
614+
///
615+
/// - Parameter value: The literal `Sendable` value to search for.
616+
/// - Returns: A new `FunctionExpression` representing the last index of the value.
617+
func arrayLastIndexOf(_ value: Sendable) -> FunctionExpression
618+
619+
/// Creates an expression that returns the index of the last occurrence of a value in an array.
620+
/// Returns nil if the value is not found.
621+
/// Assumes `self` evaluates to an array.
622+
///
623+
/// ```swift
624+
/// // Get the last index of the value of field "searchTag" in the "tags" array.
625+
/// Field("tags").arrayLastIndexOf(Field("searchTag"))
626+
/// ```
627+
///
628+
/// - Parameter value: An `Expression` representing the value to search for.
629+
/// - Returns: A new `FunctionExpression` representing the last index of the value.
630+
func arrayLastIndexOf(_ value: Expression) -> FunctionExpression
631+
632+
/// Creates an expression that returns all indices of a value in an array.
633+
/// Returns an empty array if the value is not found.
634+
/// Assumes `self` evaluates to an array.
635+
///
636+
/// ```swift
637+
/// // Get all indices of "urgent" in the "tags" array.
638+
/// Field("tags").arrayIndexOfAll("urgent")
639+
/// ```
640+
///
641+
/// - Parameter value: The literal `Sendable` value to search for.
642+
/// - Returns: A new `FunctionExpression` representing the indices of the value.
643+
func arrayIndexOfAll(_ value: Sendable) -> FunctionExpression
644+
645+
/// Creates an expression that returns all indices of a value in an array.
646+
/// Returns an empty array if the value is not found.
647+
/// Assumes `self` evaluates to an array.
648+
///
649+
/// ```swift
650+
/// // Get all indices of the value of field "searchTag" in the "tags" array.
651+
/// Field("tags").arrayIndexOfAll(Field("searchTag"))
652+
/// ```
653+
///
654+
/// - Parameter value: An `Expression` representing the value to search for.
655+
/// - Returns: A new `FunctionExpression` representing the indices of the value.
656+
func arrayIndexOfAll(_ value: Expression) -> FunctionExpression
657+
508658
/// Creates an expression that returns the maximum element of an array.
509659
///
510660
/// Assumes `self` evaluates to an array.
@@ -529,6 +679,56 @@ public protocol Expression: Sendable {
529679
/// - Returns: A new `FunctionExpression` representing the minimum element of the array.
530680
func arrayMinimum() -> FunctionExpression
531681

682+
/// Creates an expression that returns the `n` smallest elements of an array.
683+
/// Assumes `self` evaluates to an array.
684+
///
685+
/// ```swift
686+
/// // Get the 3 lowest scores in the "scores" array.
687+
/// Field("scores").arrayMinimumN(3)
688+
/// ```
689+
///
690+
/// - Parameter n: The number of elements to return.
691+
/// - Returns: A new `FunctionExpression` representing the `n` smallest elements of the array.
692+
func arrayMinimumN(_ n: Int) -> FunctionExpression
693+
694+
/// Creates an expression that returns the `n` smallest elements of an array.
695+
/// Assumes `self` evaluates to an array.
696+
///
697+
/// ```swift
698+
/// // Get the n lowest scores in the "scores" array where n is specified by field "count".
699+
/// Field("scores").arrayMinimumN(Field("count"))
700+
/// ```
701+
///
702+
/// - Parameter n: An `Expression` (evaluating to an Int) representing the number of elements to
703+
/// return.
704+
/// - Returns: A new `FunctionExpression` representing the `n` smallest elements of the array.
705+
func arrayMinimumN(_ n: Expression) -> FunctionExpression
706+
707+
/// Creates an expression that returns the `n` largest elements of an array.
708+
/// Assumes `self` evaluates to an array.
709+
///
710+
/// ```swift
711+
/// // Get the 3 highest scores in the "scores" array.
712+
/// Field("scores").arrayMaximumN(3)
713+
/// ```
714+
///
715+
/// - Parameter n: The number of elements to return.
716+
/// - Returns: A new `FunctionExpression` representing the `n` largest elements of the array.
717+
func arrayMaximumN(_ n: Int) -> FunctionExpression
718+
719+
/// Creates an expression that returns the `n` largest elements of an array.
720+
/// Assumes `self` evaluates to an array.
721+
///
722+
/// ```swift
723+
/// // Get the n highest scores in the "scores" array where n is specified by field "count".
724+
/// Field("scores").arrayMaximumN(Field("count"))
725+
/// ```
726+
///
727+
/// - Parameter n: An `Expression` (evaluating to an Int) representing the number of elements to
728+
/// return.
729+
/// - Returns: A new `FunctionExpression` representing the `n` largest elements of the array.
730+
func arrayMaximumN(_ n: Expression) -> FunctionExpression
731+
532732
/// Creates a `BooleanExpression` that returns `true` if this expression is greater
533733
/// than the given expression.
534734
///

0 commit comments

Comments
 (0)