Skip to content

Commit c008c06

Browse files
committed
arraySum and log10
1 parent 2cbd653 commit c008c06

File tree

3 files changed

+224
-36
lines changed

3 files changed

+224
-36
lines changed

packages/firestore/src/api_pipelines.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ export {
167167
error,
168168
ifAbsent,
169169
join,
170+
log10,
171+
arraySum,
170172
Expression,
171173
AliasedExpression,
172174
Field,

packages/firestore/src/lite-api/expressions.ts

Lines changed: 130 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2081,7 +2081,11 @@ export abstract class Expression implements ProtoValueSerializable, UserData {
20812081
ifAbsent(elseExpression: unknown): Expression;
20822082

20832083
ifAbsent(elseValueOrExpression: Expression | unknown): Expression {
2084-
return new FunctionExpression('if_absent', [this, valueToDefaultExpr(elseValueOrExpression)], 'ifAbsent');
2084+
return new FunctionExpression(
2085+
'if_absent',
2086+
[this, valueToDefaultExpr(elseValueOrExpression)],
2087+
'ifAbsent'
2088+
);
20852089
}
20862090

20872091
/**
@@ -2111,9 +2115,40 @@ export abstract class Expression implements ProtoValueSerializable, UserData {
21112115
join(delimiter: string): Expression;
21122116

21132117
join(delimeterValueOrExpression: string | Expression): Expression {
2114-
return new FunctionExpression('join', [this, valueToDefaultExpr(delimeterValueOrExpression)], 'join');
2118+
return new FunctionExpression(
2119+
'join',
2120+
[this, valueToDefaultExpr(delimeterValueOrExpression)],
2121+
'join'
2122+
);
21152123
}
21162124

2125+
/**
2126+
* Creates an expression that computes the base-10 logarithm of a numeric value.
2127+
*
2128+
* ```typescript
2129+
* // Compute the base-10 logarithm of the 'value' field.
2130+
* field("value").log10();
2131+
* ```
2132+
*
2133+
* @return A new {@code Expr} representing the base-10 logarithm of the numeric value.
2134+
*/
2135+
log10(): FunctionExpression {
2136+
return new FunctionExpression('log10', [this]);
2137+
}
2138+
2139+
/**
2140+
* Creates an expression that computes the sum of the elements in an array.
2141+
*
2142+
* ```typescript
2143+
* // Compute the sum of the elements in the 'scores' field.
2144+
* field("scores").arraySum();
2145+
* ```
2146+
*
2147+
* @return A new {@code Expr} representing the sum of the elements in the array.
2148+
*/
2149+
arraySum(): FunctionExpression {
2150+
return new FunctionExpression('sum', [this]);
2151+
}
21172152

21182153
// TODO(new-expression): Add new expression method definitions above this line
21192154

@@ -6861,7 +6896,11 @@ export function currentTimestamp(): FunctionExpression {
68616896
* @return A new Expression representing the error() operation.
68626897
*/
68636898
export function error(message: string): Expression {
6864-
return new FunctionExpression('error', [constant(message)], 'currentTimestamp');
6899+
return new FunctionExpression(
6900+
'error',
6901+
[constant(message)],
6902+
'currentTimestamp'
6903+
);
68656904
}
68666905

68676906
/**
@@ -7391,9 +7430,17 @@ export function ifAbsent(ifFieldName: string, elseExpr: Expression): Expression;
73917430
* @param elseValue The value that will be returned if [ifFieldName] is absent.
73927431
* @return A new Expression representing the ifAbsent operation.
73937432
*/
7394-
export function ifAbsent(ifFieldName: string | Expression, elseValue: Expression | unknown): Expression;
7395-
export function ifAbsent(fieldNameOrExpression: string | Expression, elseValue: Expression | unknown): Expression {
7396-
return fieldOrExpression(fieldNameOrExpression).ifAbsent(valueToDefaultExpr(elseValue));
7433+
export function ifAbsent(
7434+
ifFieldName: string | Expression,
7435+
elseValue: Expression | unknown
7436+
): Expression;
7437+
export function ifAbsent(
7438+
fieldNameOrExpression: string | Expression,
7439+
elseValue: Expression | unknown
7440+
): Expression {
7441+
return fieldOrExpression(fieldNameOrExpression).ifAbsent(
7442+
valueToDefaultExpr(elseValue)
7443+
);
73977444
}
73987445

73997446
/**
@@ -7422,7 +7469,10 @@ export function join(arrayFieldName: string, delimiter: string): Expression;
74227469
* @param delimiterExpression The expression that evaluates to the delimiter string.
74237470
* @return A new Expression representing the join operation.
74247471
*/
7425-
export function join(arrayExpression: Expression, delimiterExpression: Expression): Expression;
7472+
export function join(
7473+
arrayExpression: Expression,
7474+
delimiterExpression: Expression
7475+
): Expression;
74267476

74277477
/**
74287478
* Creates an expression that joins the elements of an array into a string.
@@ -7436,7 +7486,10 @@ export function join(arrayExpression: Expression, delimiterExpression: Expressio
74367486
* @param delimiter The string to use as a delimiter.
74377487
* @return A new Expression representing the join operation.
74387488
*/
7439-
export function join(arrayExpression: Expression, delimiter: string): Expression;
7489+
export function join(
7490+
arrayExpression: Expression,
7491+
delimiter: string
7492+
): Expression;
74407493

74417494
/**
74427495
* Creates an expression that joins the elements of an array into a string.
@@ -7450,9 +7503,75 @@ export function join(arrayExpression: Expression, delimiter: string): Expression
74507503
* @param delimiterExpression The expression that evaluates to the delimiter string.
74517504
* @return A new Expression representing the join operation.
74527505
*/
7453-
export function join(arrayFieldName: string, delimiterExpression: Expression): Expression;
7454-
export function join(fieldNameOrExpression: string | Expression, delimiterValueOrExpression: Expression | string): Expression {
7455-
return fieldOrExpression(fieldNameOrExpression).join(valueToDefaultExpr(delimiterValueOrExpression));
7506+
export function join(
7507+
arrayFieldName: string,
7508+
delimiterExpression: Expression
7509+
): Expression;
7510+
export function join(
7511+
fieldNameOrExpression: string | Expression,
7512+
delimiterValueOrExpression: Expression | string
7513+
): Expression {
7514+
return fieldOrExpression(fieldNameOrExpression).join(
7515+
valueToDefaultExpr(delimiterValueOrExpression)
7516+
);
7517+
}
7518+
7519+
/**
7520+
* Creates an expression that computes the base-10 logarithm of a numeric value.
7521+
*
7522+
* ```typescript
7523+
* // Compute the base-10 logarithm of the 'value' field.
7524+
* log10("value");
7525+
* ```
7526+
*
7527+
* @param fieldName The name of the field to compute the base-10 logarithm of.
7528+
* @return A new `Expr` representing the base-10 logarithm of the numeric value.
7529+
*/
7530+
export function log10(fieldName: string): FunctionExpression;
7531+
7532+
/**
7533+
* Creates an expression that computes the base-10 logarithm of a numeric value.
7534+
*
7535+
* ```typescript
7536+
* // Compute the base-10 logarithm of the 'value' field.
7537+
* log10(field("value"));
7538+
* ```
7539+
*
7540+
* @param expression An expression evaluating to a numeric value, which the base-10 logarithm will be computed for.
7541+
* @return A new `Expr` representing the base-10 logarithm of the numeric value.
7542+
*/
7543+
export function log10(expression: Expression): FunctionExpression;
7544+
export function log10(expr: Expression | string): FunctionExpression {
7545+
return fieldOrExpression(expr).log10();
7546+
}
7547+
7548+
/**
7549+
* Creates an expression that computes the sum of the elements in an array.
7550+
*
7551+
* ```typescript
7552+
* // Compute the sum of the elements in the 'scores' field.
7553+
* arraySum("scores");
7554+
* ```
7555+
*
7556+
* @param fieldName The name of the field to compute the sum of.
7557+
* @return A new `Expr` representing the sum of the elements in the array.
7558+
*/
7559+
export function arraySum(fieldName: string): FunctionExpression;
7560+
7561+
/**
7562+
* Creates an expression that computes the sum of the elements in an array.
7563+
*
7564+
* ```typescript
7565+
* // Compute the sum of the elements in the 'scores' field.
7566+
* arraySum(field("scores"));
7567+
* ```
7568+
*
7569+
* @param expression An expression evaluating to a numeric array, which the sum will be computed for.
7570+
* @return A new `Expr` representing the sum of the elements in the array.
7571+
*/
7572+
export function arraySum(expression: Expression): FunctionExpression;
7573+
export function arraySum(expr: Expression | string): FunctionExpression {
7574+
return fieldOrExpression(expr).arraySum();
74567575
}
74577576

74587577
// TODO(new-expression): Add new top-level expression function definitions above this line

packages/firestore/test/integration/api/pipeline.test.ts

Lines changed: 92 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,11 @@ import {
141141
abs,
142142
concat,
143143
error,
144-
currentTimestamp, ifAbsent, join
144+
currentTimestamp,
145+
ifAbsent,
146+
join,
147+
log10,
148+
arraySum
145149
} from '../util/pipeline_export';
146150

147151
use(chaiAsPromised);
@@ -3821,6 +3825,36 @@ apiDescribe.only('Pipelines', persistence => {
38213825
});
38223826
});
38233827

3828+
it('can compute the base-10 logarithm of a numeric value', async () => {
3829+
const snapshot = await execute(
3830+
firestore
3831+
.pipeline()
3832+
.collection(randomCol.path)
3833+
.where(field('title').equal('The Lord of the Rings'))
3834+
.limit(1)
3835+
.select(field('rating').log10().as('log10Rating'))
3836+
);
3837+
expect(snapshot.results[0]!.data().log10Rating).to.be.closeTo(
3838+
0.672,
3839+
0.001
3840+
);
3841+
});
3842+
3843+
it('can compute the base-10 logarithm of a numeric value with the top-level function', async () => {
3844+
const snapshot = await execute(
3845+
firestore
3846+
.pipeline()
3847+
.collection(randomCol.path)
3848+
.where(field('title').equal('The Lord of the Rings'))
3849+
.limit(1)
3850+
.select(log10('rating').as('log10Rating'))
3851+
);
3852+
expect(snapshot.results[0]!.data().log10Rating).to.be.closeTo(
3853+
0.672,
3854+
0.001
3855+
);
3856+
});
3857+
38243858
it('can concat fields', async () => {
38253859
const snapshot = await execute(
38263860
firestore
@@ -3845,28 +3879,28 @@ apiDescribe.only('Pipelines', persistence => {
38453879
.pipeline()
38463880
.collection(randomCol.path)
38473881
.limit(1)
3848-
.addFields(
3849-
currentTimestamp().as('now')
3850-
)
3882+
.addFields(currentTimestamp().as('now'))
38513883
.select('now')
38523884
);
3853-
let now = snapshot.results[0].get('now') as Timestamp;
3885+
const now = snapshot.results[0].get('now') as Timestamp;
38543886
expect(now).instanceof(Timestamp);
3855-
expect(now.toDate().getUTCSeconds() - (new Date()).getUTCSeconds()).lessThan(5000);
3887+
expect(
3888+
now.toDate().getUTCSeconds() - new Date().getUTCSeconds()
3889+
).lessThan(5000);
38563890
});
38573891

3858-
it('supports error', async () => {
3892+
// Not implemented in backend
3893+
it.skip('supports error', async () => {
38593894
const snapshot = await execute(
38603895
firestore
38613896
.pipeline()
38623897
.collection(randomCol.path)
38633898
.limit(1)
3864-
.select(
3865-
isError(error('test error')).as('error')
3866-
));
3899+
.select(isError(error('test error')).as('error'))
3900+
);
38673901

38683902
expectResults(snapshot, {
3869-
'error': true,
3903+
'error': true
38703904
});
38713905
});
38723906

@@ -3876,14 +3910,17 @@ apiDescribe.only('Pipelines', persistence => {
38763910
.pipeline()
38773911
.collection(randomCol.path)
38783912
.limit(1)
3879-
.replaceWith(map({
3880-
title: 'foo'
3881-
}))
3913+
.replaceWith(
3914+
map({
3915+
title: 'foo'
3916+
})
3917+
)
38823918
.select(
38833919
ifAbsent('title', 'default title').as('title'),
38843920
field('name').ifAbsent('default name').as('name'),
3885-
field('name').ifAbsent(field('title')).as('nameOrTitle'),
3886-
));
3921+
field('name').ifAbsent(field('title')).as('nameOrTitle')
3922+
)
3923+
);
38873924

38883925
expectResults(snapshot, {
38893926
title: 'foo',
@@ -3892,27 +3929,57 @@ apiDescribe.only('Pipelines', persistence => {
38923929
});
38933930
});
38943931

3895-
it.only('supports join', async () => {
3932+
it('supports join', async () => {
38963933
const snapshot = await execute(
38973934
firestore
38983935
.pipeline()
38993936
.collection(randomCol.path)
39003937
.limit(1)
3901-
.replaceWith(map({
3902-
tags: ['foo', 'bar', 'baz'],
3903-
delimeter: '|'
3904-
}))
3905-
.select(
3906-
join('tags', ',').as('csv'),
3907-
field('tags').join('|').as('or')
3908-
));
3938+
.replaceWith(
3939+
map({
3940+
tags: ['foo', 'bar', 'baz'],
3941+
delimeter: '|'
3942+
})
3943+
)
3944+
.select(join('tags', ',').as('csv'), field('tags').join('|').as('or'))
3945+
);
39093946

39103947
expectResults(snapshot, {
39113948
csv: 'foo,bar,baz',
39123949
or: 'foo|bar|baz'
39133950
});
39143951
});
39153952

3953+
it('can compute the sum of the elements in an array', async () => {
3954+
const snapshot = await execute(
3955+
firestore
3956+
.pipeline()
3957+
.collection(randomCol.path)
3958+
.where(field('title').equal('The Lord of the Rings'))
3959+
.limit(1)
3960+
.addFields(array([150, 200]).as('sales'))
3961+
.select(field('sales').arraySum().as('totalSales'))
3962+
);
3963+
expectResults(snapshot, {
3964+
totalSales: 350
3965+
});
3966+
});
3967+
3968+
it('can compute the sum of the elements in an array with the top-level function', async () => {
3969+
const snapshot = await execute(
3970+
firestore
3971+
.pipeline()
3972+
.collection(randomCol.path)
3973+
.where(field('title').equal('The Lord of the Rings'))
3974+
.limit(1)
3975+
.addFields(array([150, 200]).as('sales'))
3976+
.select(arraySum('sales').as('totalSales'))
3977+
);
3978+
expectResults(snapshot, {
3979+
totalSales: 350
3980+
});
3981+
});
3982+
39163983
// TODO(new-expression): Add new expression tests above this line
39173984
});
39183985

0 commit comments

Comments
 (0)