Skip to content

Commit 62dd17f

Browse files
milaGGLthiyaguk09
authored andcommitted
add arrayTransform
1 parent d724c03 commit 62dd17f

3 files changed

Lines changed: 251 additions & 7 deletions

File tree

handwritten/firestore/dev/src/pipelines/expression.ts

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,59 @@ export abstract class Expression
667667
]);
668668
}
669669

670+
/**
671+
* @beta
672+
* Creates an expression that applies a provided transformation to each element in an array.
673+
*
674+
* @example
675+
* ```typescript
676+
* // Transform the 'scores' array by multiplying each score by 10
677+
* field("scores").arrayTransform("score", multiply(variable("score"), 10));
678+
* ```
679+
*
680+
* @param elementAlias The variable name to use for each element.
681+
* @param transform The lambda expression used to transform the elements.
682+
* @returns A new `Expression` representing the arrayTransform operation.
683+
*/
684+
arrayTransform(
685+
elementAlias: string,
686+
transform: Expression,
687+
): FunctionExpression {
688+
return new FunctionExpression('array_transform', [
689+
this,
690+
valueToDefaultExpr(elementAlias),
691+
transform,
692+
]);
693+
}
694+
695+
/**
696+
* @beta
697+
* Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression.
698+
*
699+
* @example
700+
* ```typescript
701+
* // Transform the 'scores' array by adding the index to each score
702+
* field("scores").arrayTransformWithIndex("score", "i", add(variable("score"), variable("i")));
703+
* ```
704+
*
705+
* @param elementAlias The variable name to use for each element.
706+
* @param indexAlias The variable name to use for the current index.
707+
* @param transform The lambda expression used to transform the elements.
708+
* @returns A new `Expression` representing the arrayTransform operation.
709+
*/
710+
arrayTransformWithIndex(
711+
elementAlias: string,
712+
indexAlias: string,
713+
transform: Expression,
714+
): FunctionExpression {
715+
return new FunctionExpression('array_transform', [
716+
this,
717+
valueToDefaultExpr(elementAlias),
718+
valueToDefaultExpr(indexAlias),
719+
transform,
720+
]);
721+
}
722+
670723
/**
671724
* @beta
672725
* Returns a subset of the array.
@@ -6296,6 +6349,109 @@ export function arrayFilter(
62966349
return fieldOrExpression(array).arrayFilter(alias, filter);
62976350
}
62986351

6352+
/**
6353+
* @beta
6354+
* Creates an expression that applies a provided transformation to each element in an array.
6355+
*
6356+
* ```typescript
6357+
* // Transform "scores" array by multiplying each score by 10
6358+
* arrayTransform("scores", "score", multiply(variable("score"), 10));
6359+
* ```
6360+
*
6361+
* @param fieldName The name of the field containing the array.
6362+
* @param elementAlias The variable name to use for each element.
6363+
* @param transform The lambda expression used to transform the elements.
6364+
* @returns A new `Expression` representing the transformed array.
6365+
*/
6366+
export function arrayTransform(
6367+
fieldName: string,
6368+
elementAlias: string,
6369+
transform: Expression,
6370+
): FunctionExpression;
6371+
6372+
/**
6373+
* @beta
6374+
* Creates an expression that applies a provided transformation to each element in an array.
6375+
*
6376+
* ```typescript
6377+
* // Transform "scores" array by multiplying each score by 10
6378+
* arrayTransform(field("scores"), "score", multiply(variable("score"), 10));
6379+
* ```
6380+
*
6381+
* @param arrayExpression The expression representing the array.
6382+
* @param elementAlias The variable name to use for each element.
6383+
* @param transform The lambda expression used to transform the elements.
6384+
* @returns A new `Expression` representing the transformed array.
6385+
*/
6386+
export function arrayTransform(
6387+
arrayExpression: Expression,
6388+
elementAlias: string,
6389+
transform: Expression,
6390+
): FunctionExpression;
6391+
export function arrayTransform(
6392+
array: Expression | string,
6393+
elementAlias: string,
6394+
transform: Expression,
6395+
): FunctionExpression {
6396+
return fieldOrExpression(array).arrayTransform(elementAlias, transform);
6397+
}
6398+
6399+
/**
6400+
* @beta
6401+
* Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression.
6402+
*
6403+
* ```typescript
6404+
* // Transform "scores" array by adding the index to each score
6405+
* arrayTransformWithIndex("scores", "score", "i", add(variable("score"), variable("i")));
6406+
* ```
6407+
*
6408+
* @param fieldName The name of the field containing the array.
6409+
* @param elementAlias The variable name to use for each element.
6410+
* @param indexAlias The variable name to use for the current index.
6411+
* @param transform The lambda expression used to transform the elements.
6412+
* @returns A new `Expression` representing the transformed array.
6413+
*/
6414+
export function arrayTransformWithIndex(
6415+
fieldName: string,
6416+
elementAlias: string,
6417+
indexAlias: string,
6418+
transform: Expression,
6419+
): FunctionExpression;
6420+
6421+
/**
6422+
* @beta
6423+
* Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression.
6424+
*
6425+
* ```typescript
6426+
* // Transform "scores" array by adding the index to each score
6427+
* arrayTransformWithIndex(field("scores"), "score", "i", add(variable("score"), variable("i")));
6428+
* ```
6429+
*
6430+
* @param arrayExpression The expression representing the array.
6431+
* @param elementAlias The variable name to use for each element.
6432+
* @param indexAlias The variable name to use for the current index.
6433+
* @param transform The expression used to transform the elements.
6434+
* @returns A new `Expression` representing the transformed array.
6435+
*/
6436+
export function arrayTransformWithIndex(
6437+
arrayExpression: Expression,
6438+
elementAlias: string,
6439+
indexAlias: string,
6440+
transform: Expression,
6441+
): FunctionExpression;
6442+
export function arrayTransformWithIndex(
6443+
array: Expression | string,
6444+
elementAlias: string,
6445+
indexAlias: string,
6446+
transform: Expression,
6447+
): FunctionExpression {
6448+
return fieldOrExpression(array).arrayTransformWithIndex(
6449+
elementAlias,
6450+
indexAlias,
6451+
transform,
6452+
);
6453+
}
6454+
62996455
/**
63006456
* @beta
63016457
* Creates an expression that returns a subset of an array.

handwritten/firestore/dev/src/pipelines/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ export {
6969
arrayMaximumN,
7070
arrayMinimumN,
7171
arrayFilter,
72+
arrayTransform,
73+
arrayTransformWithIndex,
7274
arraySlice,
7375
field,
7476
xor,

handwritten/firestore/dev/system-test/pipeline.ts

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ import {
148148
currentTimestamp,
149149
arrayConcat,
150150
arrayFilter,
151+
arrayTransform,
152+
arrayTransformWithIndex,
151153
arraySlice,
152154
type,
153155
isType,
@@ -3497,14 +3499,14 @@ async function testCollectionWithDocs(
34973499
.collection(randomCol.path)
34983500
.where(equal('title', 'The Lord of the Rings'))
34993501
.select(
3500-
arrayFilter('tags', 'tag', notEqual(field('tag'), 'magic')).as(
3502+
arrayFilter('tags', 'tag', notEqual(variable('tag'), 'magic')).as(
35013503
'notMagicTags',
35023504
),
35033505
field('tags')
3504-
.arrayFilter('tag', notEqual(field('tag'), 'epic'))
3506+
.arrayFilter('tag', notEqual(variable('tag'), 'epic'))
35053507
.as('notEpicTags'),
35063508
field('tags')
3507-
.arrayFilter('tag', equal(field('tag'), 'fantasy'))
3509+
.arrayFilter('tag', equal(variable('tag'), 'fantasy'))
35083510
.as('noMatchingTags'),
35093511
)
35103512
.execute();
@@ -3516,7 +3518,7 @@ async function testCollectionWithDocs(
35163518
});
35173519
});
35183520

3519-
it.only('supports arrayFilter with mixed types and nulls', async () => {
3521+
it('supports arrayFilter with mixed types and nulls', async () => {
35203522
const snapshot = await firestore
35213523
.pipeline()
35223524
.collection(randomCol.path)
@@ -3527,16 +3529,100 @@ async function testCollectionWithDocs(
35273529
}),
35283530
)
35293531
.select(
3530-
arrayFilter('arr', 'element', greaterThan(field('element'), 10)).as(
3531-
'filtered',
3532-
),
3532+
arrayFilter(
3533+
'arr',
3534+
'element',
3535+
greaterThan(variable('element'), 10),
3536+
).as('filtered'),
35333537
)
35343538
.execute();
35353539

35363540
const res = snapshot.results[0].data();
35373541
expect(res.filtered).to.have.members([20.0, 30]);
35383542
});
35393543

3544+
it('supports arrayTransform and arrayTransformWithIndex', async () => {
3545+
const snapshot = await firestore
3546+
.pipeline()
3547+
.collection(randomCol.path)
3548+
.limit(1)
3549+
.replaceWith(map({arr: [10, 20, 30]}))
3550+
.select(
3551+
arrayTransform(
3552+
'arr',
3553+
'element',
3554+
multiply(variable('element'), 10),
3555+
).as('staticTransform'),
3556+
field('arr')
3557+
.arrayTransform('element', multiply(variable('element'), 10))
3558+
.as('instanceTransform'),
3559+
arrayTransformWithIndex(
3560+
'arr',
3561+
'element',
3562+
'i',
3563+
add(variable('element'), variable('i')),
3564+
).as('staticTransformWithIndex'),
3565+
field('arr')
3566+
.arrayTransformWithIndex(
3567+
'element',
3568+
'i',
3569+
add(variable('element'), variable('i')),
3570+
)
3571+
.as('instanceTransformWithIndex'),
3572+
)
3573+
.execute();
3574+
3575+
expectResults(snapshot, {
3576+
staticTransform: [100, 200, 300],
3577+
instanceTransform: [100, 200, 300],
3578+
staticTransformWithIndex: [10, 21, 32],
3579+
instanceTransformWithIndex: [10, 21, 32],
3580+
});
3581+
});
3582+
3583+
it('supports arrayTransform with empty array and nulls', async () => {
3584+
const snapshot = await firestore
3585+
.pipeline()
3586+
.collection(randomCol.path)
3587+
.limit(1)
3588+
.replaceWith(
3589+
map({
3590+
arr: [1, null, 3],
3591+
empty: [],
3592+
}),
3593+
)
3594+
.select(
3595+
field('arr')
3596+
.arrayTransform('element', add(variable('element'), 1))
3597+
.as('transformedWithNulls'),
3598+
field('empty')
3599+
.arrayTransform('element', add(variable('element'), 1))
3600+
.as('transformedEmpty'),
3601+
field('arr')
3602+
.arrayTransformWithIndex(
3603+
'element',
3604+
'idx',
3605+
add(variable('element'), variable('idx')),
3606+
)
3607+
.as('transformedWithIndex'),
3608+
field('empty')
3609+
.arrayTransformWithIndex(
3610+
'element',
3611+
'idx',
3612+
add(variable('element'), variable('idx')),
3613+
)
3614+
.as('transformedEmptyWithIndex'),
3615+
)
3616+
.execute();
3617+
3618+
expectResults(snapshot, {
3619+
transformedWithNulls: [2, null, 4],
3620+
transformedEmpty: [],
3621+
transformedWithIndex: [1, null, 5],
3622+
transformedEmptyWithIndex: [],
3623+
});
3624+
});
3625+
35403626
it('supports arraySlice', async () => {
35413627
const snapshot = await firestore
35423628
.pipeline()

0 commit comments

Comments
 (0)