Skip to content

Commit 659d9bb

Browse files
authored
feat(firestore): add accumulators expressions (#9576)
* add first and last aggregation expressions * add array_agg aggregation expression * add array_agg_distinct aggregation expression * Add changeset and documentation * fix formatting * add remark documentation for array_agg and array_agg_distinct
1 parent 852162b commit 659d9bb

File tree

12 files changed

+1224
-0
lines changed

12 files changed

+1224
-0
lines changed

.changeset/few-dodos-ring.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'firebase': minor
3+
'@firebase/firestore': minor
4+
---
5+
6+
Add support for first, last, array_agg and array_agg_distinct expressions

common/api-review/firestore-lite-pipelines.api.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ export function and(first: BooleanExpression, second: BooleanExpression, ...more
6565
// @beta
6666
export function array(elements: unknown[]): FunctionExpression;
6767

68+
// @beta
69+
export function arrayAgg(expression: Expression): AggregateFunction;
70+
71+
// @beta
72+
export function arrayAgg(fieldName: string): AggregateFunction;
73+
74+
// @beta
75+
export function arrayAggDistinct(expression: Expression): AggregateFunction;
76+
77+
// @beta
78+
export function arrayAggDistinct(fieldName: string): AggregateFunction;
79+
6880
// @beta
6981
export function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array<Expression | unknown[]>): FunctionExpression;
7082

@@ -377,6 +389,10 @@ export abstract class Expression {
377389
/* Excluded from this release type: _readUserData */
378390
add(second: Expression | unknown): FunctionExpression;
379391
/* Excluded from this release type: _readUserData */
392+
arrayAgg(): AggregateFunction;
393+
/* Excluded from this release type: _readUserData */
394+
arrayAggDistinct(): AggregateFunction;
395+
/* Excluded from this release type: _readUserData */
380396
arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array<Expression | unknown[]>): FunctionExpression;
381397
/* Excluded from this release type: _readUserData */
382398
arrayContains(expression: Expression): BooleanExpression;
@@ -462,6 +478,8 @@ export abstract class Expression {
462478
// (undocumented)
463479
abstract readonly expressionType: ExpressionType;
464480
/* Excluded from this release type: _readUserData */
481+
first(): AggregateFunction;
482+
/* Excluded from this release type: _readUserData */
465483
floor(): FunctionExpression;
466484
/* Excluded from this release type: _readUserData */
467485
greaterThan(expression: Expression): BooleanExpression;
@@ -488,6 +506,8 @@ export abstract class Expression {
488506
/* Excluded from this release type: _readUserData */
489507
join(delimiter: string): Expression;
490508
/* Excluded from this release type: _readUserData */
509+
last(): AggregateFunction;
510+
/* Excluded from this release type: _readUserData */
491511
length(): FunctionExpression;
492512
/* Excluded from this release type: _readUserData */
493513
lessThan(experession: Expression): BooleanExpression;
@@ -677,6 +697,12 @@ export type FindNearestStageOptions = StageOptions & {
677697
distanceField?: string;
678698
};
679699

700+
// @beta
701+
export function first(expression: Expression): AggregateFunction;
702+
703+
// @beta
704+
export function first(fieldName: string): AggregateFunction;
705+
680706
// @beta
681707
export function floor(expr: Expression): FunctionExpression;
682708

@@ -757,6 +783,12 @@ export function join(arrayExpression: Expression, delimiter: string): Expression
757783
// @beta
758784
export function join(arrayFieldName: string, delimiterExpression: Expression): Expression;
759785

786+
// @beta
787+
export function last(expression: Expression): AggregateFunction;
788+
789+
// @beta
790+
export function last(fieldName: string): AggregateFunction;
791+
760792
// @beta
761793
function length_2(fieldName: string): FunctionExpression;
762794

common/api-review/firestore-pipelines.api.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,18 @@ export function and(first: BooleanExpression, second: BooleanExpression, ...more
6565
// @beta
6666
export function array(elements: unknown[]): FunctionExpression;
6767

68+
// @beta
69+
export function arrayAgg(expression: Expression): AggregateFunction;
70+
71+
// @beta
72+
export function arrayAgg(fieldName: string): AggregateFunction;
73+
74+
// @beta
75+
export function arrayAggDistinct(expression: Expression): AggregateFunction;
76+
77+
// @beta
78+
export function arrayAggDistinct(fieldName: string): AggregateFunction;
79+
6880
// @beta
6981
export function arrayConcat(firstArray: Expression, secondArray: Expression | unknown[], ...otherArrays: Array<Expression | unknown[]>): FunctionExpression;
7082

@@ -380,6 +392,10 @@ export abstract class Expression {
380392
/* Excluded from this release type: _readUserData */
381393
add(second: Expression | unknown): FunctionExpression;
382394
/* Excluded from this release type: _readUserData */
395+
arrayAgg(): AggregateFunction;
396+
/* Excluded from this release type: _readUserData */
397+
arrayAggDistinct(): AggregateFunction;
398+
/* Excluded from this release type: _readUserData */
383399
arrayConcat(secondArray: Expression | unknown[], ...otherArrays: Array<Expression | unknown[]>): FunctionExpression;
384400
/* Excluded from this release type: _readUserData */
385401
arrayContains(expression: Expression): BooleanExpression;
@@ -465,6 +481,8 @@ export abstract class Expression {
465481
// (undocumented)
466482
abstract readonly expressionType: ExpressionType;
467483
/* Excluded from this release type: _readUserData */
484+
first(): AggregateFunction;
485+
/* Excluded from this release type: _readUserData */
468486
floor(): FunctionExpression;
469487
/* Excluded from this release type: _readUserData */
470488
greaterThan(expression: Expression): BooleanExpression;
@@ -491,6 +509,8 @@ export abstract class Expression {
491509
/* Excluded from this release type: _readUserData */
492510
join(delimiter: string): Expression;
493511
/* Excluded from this release type: _readUserData */
512+
last(): AggregateFunction;
513+
/* Excluded from this release type: _readUserData */
494514
length(): FunctionExpression;
495515
/* Excluded from this release type: _readUserData */
496516
lessThan(experession: Expression): BooleanExpression;
@@ -680,6 +700,12 @@ export type FindNearestStageOptions = StageOptions & {
680700
distanceField?: string;
681701
};
682702

703+
// @beta
704+
export function first(expression: Expression): AggregateFunction;
705+
706+
// @beta
707+
export function first(fieldName: string): AggregateFunction;
708+
683709
// @beta
684710
export function floor(expr: Expression): FunctionExpression;
685711

@@ -760,6 +786,12 @@ export function join(arrayExpression: Expression, delimiter: string): Expression
760786
// @beta
761787
export function join(arrayFieldName: string, delimiterExpression: Expression): Expression;
762788

789+
// @beta
790+
export function last(expression: Expression): AggregateFunction;
791+
792+
// @beta
793+
export function last(fieldName: string): AggregateFunction;
794+
763795
// @beta
764796
function length_2(fieldName: string): FunctionExpression;
765797

docs-devsite/firestore_lite_pipelines.expression.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ export declare abstract class Expression
3939
| --- | --- | --- |
4040
| [abs()](./firestore_lite_pipelines.expression.md#expressionabs) | | <b><i>(Public Preview)</i></b> Creates an expression that computes the absolute value of a numeric value. |
4141
| [add(second)](./firestore_lite_pipelines.expression.md#expressionadd) | | <b><i>(Public Preview)</i></b> Creates an expression that adds this expression to another expression. |
42+
| [arrayAgg()](./firestore_lite_pipelines.expression.md#expressionarrayagg) | | <b><i>(Public Preview)</i></b> Creates an aggregation that collects all values of an expression across multiple stage inputs into an array. |
43+
| [arrayAggDistinct()](./firestore_lite_pipelines.expression.md#expressionarrayaggdistinct) | | <b><i>(Public Preview)</i></b> Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array. |
4244
| [arrayConcat(secondArray, otherArrays)](./firestore_lite_pipelines.expression.md#expressionarrayconcat) | | <b><i>(Public Preview)</i></b> Creates an expression that concatenates an array expression with one or more other arrays. |
4345
| [arrayContains(expression)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if an array contains a specific element. |
4446
| [arrayContains(value)](./firestore_lite_pipelines.expression.md#expressionarraycontains) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if an array contains a specific value. |
@@ -80,6 +82,7 @@ export declare abstract class Expression
8082
| [euclideanDistance(vector)](./firestore_lite_pipelines.expression.md#expressioneuclideandistance) | | <b><i>(Public Preview)</i></b> Calculates the Euclidean distance between two vectors. |
8183
| [exists()](./firestore_lite_pipelines.expression.md#expressionexists) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if a field exists in the document. |
8284
| [exp()](./firestore_lite_pipelines.expression.md#expressionexp) | | <b><i>(Public Preview)</i></b> Creates an expression that computes e to the power of this expression. |
85+
| [first()](./firestore_lite_pipelines.expression.md#expressionfirst) | | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the first value of an expression across multiple stage inputs. |
8386
| [floor()](./firestore_lite_pipelines.expression.md#expressionfloor) | | <b><i>(Public Preview)</i></b> Creates an expression that computes the floor of a numeric value. |
8487
| [greaterThan(expression)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if this expression is greater than another expression. |
8588
| [greaterThan(value)](./firestore_lite_pipelines.expression.md#expressiongreaterthan) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if this expression is greater than a constant value. |
@@ -100,6 +103,7 @@ field("optional_field").ifAbsent(field('default_field'))
100103
| [isError()](./firestore_lite_pipelines.expression.md#expressioniserror) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if a given expression produces an error. |
101104
| [join(delimiterExpression)](./firestore_lite_pipelines.expression.md#expressionjoin) | | <b><i>(Public Preview)</i></b> Creates an expression that joins the elements of an array into a string. |
102105
| [join(delimiter)](./firestore_lite_pipelines.expression.md#expressionjoin) | | <b><i>(Public Preview)</i></b> Creates an expression that joins the elements of an array field into a string. |
106+
| [last()](./firestore_lite_pipelines.expression.md#expressionlast) | | <b><i>(Public Preview)</i></b> Creates an aggregation that finds the last value of an expression across multiple stage inputs. |
103107
| [length()](./firestore_lite_pipelines.expression.md#expressionlength) | | <b><i>(Public Preview)</i></b> Creates an expression that calculates the length of a string, array, map, vector, or bytes. |
104108
| [lessThan(experession)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if this expression is less than another expression. |
105109
| [lessThan(value)](./firestore_lite_pipelines.expression.md#expressionlessthan) | | <b><i>(Public Preview)</i></b> Creates an expression that checks if this expression is less than a constant value. |
@@ -251,6 +255,64 @@ field("quantity").add(field("reserve"));
251255

252256
```
253257

258+
## Expression.arrayAgg()
259+
260+
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
261+
>
262+
263+
Creates an aggregation that collects all values of an expression across multiple stage inputs into an array.
264+
265+
If the expression resolves to an absent value, it is converted to `null`<!-- -->. The order of elements in the output array is not stable and shouldn't be relied upon.
266+
267+
<b>Signature:</b>
268+
269+
```typescript
270+
arrayAgg(): AggregateFunction;
271+
```
272+
<b>Returns:</b>
273+
274+
[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class)
275+
276+
A new `AggregateFunction` representing the 'array\_agg' aggregation.
277+
278+
### Example
279+
280+
281+
```typescript
282+
// Collect all tags from books into an array
283+
field("tags").arrayAgg().as("allTags");
284+
285+
```
286+
287+
## Expression.arrayAggDistinct()
288+
289+
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
290+
>
291+
292+
Creates an aggregation that collects all distinct values of an expression across multiple stage inputs into an array.
293+
294+
If the expression resolves to an absent value, it is converted to `null`<!-- -->. The order of elements in the output array is not stable and shouldn't be relied upon.
295+
296+
<b>Signature:</b>
297+
298+
```typescript
299+
arrayAggDistinct(): AggregateFunction;
300+
```
301+
<b>Returns:</b>
302+
303+
[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class)
304+
305+
A new `AggregateFunction` representing the 'array\_agg\_distinct' aggregation.
306+
307+
### Example
308+
309+
310+
```typescript
311+
// Collect all distinct tags from books into an array
312+
field("tags").arrayAggDistinct().as("allDistinctTags");
313+
314+
```
315+
254316
## Expression.arrayConcat()
255317

256318
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -1533,6 +1595,33 @@ field("value").exp();
15331595

15341596
```
15351597

1598+
## Expression.first()
1599+
1600+
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
1601+
>
1602+
1603+
Creates an aggregation that finds the first value of an expression across multiple stage inputs.
1604+
1605+
<b>Signature:</b>
1606+
1607+
```typescript
1608+
first(): AggregateFunction;
1609+
```
1610+
<b>Returns:</b>
1611+
1612+
[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class)
1613+
1614+
A new `AggregateFunction` representing the 'first' aggregation.
1615+
1616+
### Example
1617+
1618+
1619+
```typescript
1620+
// Find the first value of the 'rating' field
1621+
field("rating").first().as("firstRating");
1622+
1623+
```
1624+
15361625
## Expression.floor()
15371626

15381627
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
@@ -1956,6 +2045,33 @@ field("tags").join(", ")
19562045

19572046
```
19582047

2048+
## Expression.last()
2049+
2050+
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.
2051+
>
2052+
2053+
Creates an aggregation that finds the last value of an expression across multiple stage inputs.
2054+
2055+
<b>Signature:</b>
2056+
2057+
```typescript
2058+
last(): AggregateFunction;
2059+
```
2060+
<b>Returns:</b>
2061+
2062+
[AggregateFunction](./firestore_lite_pipelines.aggregatefunction.md#aggregatefunction_class)
2063+
2064+
A new `AggregateFunction` representing the 'last' aggregation.
2065+
2066+
### Example
2067+
2068+
2069+
```typescript
2070+
// Find the last value of the 'rating' field
2071+
field("rating").last().as("lastRating");
2072+
2073+
```
2074+
19592075
## Expression.length()
19602076

19612077
> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment.

0 commit comments

Comments
 (0)