diff --git a/api-report/firestore.api.md b/api-report/firestore.api.md index 193aec259..7f57f1bb5 100644 --- a/api-report/firestore.api.md +++ b/api-report/firestore.api.md @@ -223,6 +223,24 @@ function arrayContainsAny(array: Expression, values: Expression): BooleanExpress // @beta function arrayContainsAny(fieldName: string, values: Expression): BooleanExpression; +// @beta +function arrayFirst(fieldName: string): FunctionExpression; + +// @beta +function arrayFirst(arrayExpression: Expression): FunctionExpression; + +// @beta +function arrayFirstN(fieldName: string, n: number): FunctionExpression; + +// @beta +function arrayFirstN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +function arrayFirstN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +function arrayFirstN(arrayExpression: Expression, n: Expression): FunctionExpression; + // @beta function arrayGet(arrayField: string, index: number): FunctionExpression; @@ -235,12 +253,84 @@ function arrayGet(arrayExpression: Expression, index: number): FunctionExpressio // @beta function arrayGet(arrayExpression: Expression, indexExpr: Expression): FunctionExpression; +// @beta +function arrayIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; + +// @beta +function arrayIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; + +// @beta +function arrayIndexOfAll(fieldName: string, search: unknown | Expression): FunctionExpression; + +// @beta +function arrayIndexOfAll(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; + +// @beta +function arrayLast(fieldName: string): FunctionExpression; + +// @beta +function arrayLast(arrayExpression: Expression): FunctionExpression; + +// @beta +function arrayLastIndexOf(fieldName: string, search: unknown | Expression): FunctionExpression; + +// @beta +function arrayLastIndexOf(arrayExpression: Expression, search: unknown | Expression): FunctionExpression; + +// @beta +function arrayLastN(fieldName: string, n: number): FunctionExpression; + +// @beta +function arrayLastN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +function arrayLastN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +function arrayLastN(arrayExpression: Expression, n: Expression): FunctionExpression; + // @beta function arrayLength(fieldName: string): FunctionExpression; // @beta function arrayLength(array: Expression): FunctionExpression; +// @beta +function arrayMaximum(fieldName: string): FunctionExpression; + +// @beta +function arrayMaximum(arrayExpression: Expression): FunctionExpression; + +// @beta +function arrayMaximumN(fieldName: string, n: number): FunctionExpression; + +// @beta +function arrayMaximumN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +function arrayMaximumN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +function arrayMaximumN(arrayExpression: Expression, n: Expression): FunctionExpression; + +// @beta +function arrayMinimum(fieldName: string): FunctionExpression; + +// @beta +function arrayMinimum(arrayExpression: Expression): FunctionExpression; + +// @beta +function arrayMinimumN(fieldName: string, n: number): FunctionExpression; + +// @beta +function arrayMinimumN(fieldName: string, n: Expression): FunctionExpression; + +// @beta +function arrayMinimumN(arrayExpression: Expression, n: number): FunctionExpression; + +// @beta +function arrayMinimumN(arrayExpression: Expression, n: Expression): FunctionExpression; + // @beta function arrayReverse(fieldName: string): FunctionExpression; @@ -979,9 +1069,27 @@ abstract class Expression implements firestore.Pipelines.Expression, HasUserData arrayContainsAll(arrayExpression: Expression): BooleanExpression; arrayContainsAny(values: Array): BooleanExpression; arrayContainsAny(arrayExpression: Expression): BooleanExpression; + arrayFirst(): FunctionExpression; + arrayFirstN(n: number): FunctionExpression; + arrayFirstN(n: Expression): FunctionExpression; arrayGet(index: number): FunctionExpression; arrayGet(indexExpr: Expression): FunctionExpression; + arrayIndexOf(search: unknown): FunctionExpression; + arrayIndexOf(search: Expression): FunctionExpression; + arrayIndexOfAll(search: unknown): FunctionExpression; + arrayIndexOfAll(search: Expression): FunctionExpression; + arrayLast(): FunctionExpression; + arrayLastIndexOf(search: unknown): FunctionExpression; + arrayLastIndexOf(search: Expression): FunctionExpression; + arrayLastN(n: number): FunctionExpression; + arrayLastN(n: Expression): FunctionExpression; arrayLength(): FunctionExpression; + arrayMaximum(): FunctionExpression; + arrayMaximumN(n: number): FunctionExpression; + arrayMaximumN(n: Expression): FunctionExpression; + arrayMinimum(): FunctionExpression; + arrayMinimumN(n: number): FunctionExpression; + arrayMinimumN(n: Expression): FunctionExpression; arrayReverse(): FunctionExpression; arraySum(): FunctionExpression; as(name: string): AliasedExpression; @@ -1901,6 +2009,17 @@ declare namespace Pipelines { equalAny, map, array, + arrayFirst, + arrayLast, + arrayFirstN, + arrayLastN, + arrayIndexOf, + arrayIndexOfAll, + arrayLastIndexOf, + arrayMaximum, + arrayMinimum, + arrayMaximumN, + arrayMinimumN, field, xor, AggregateFunction, diff --git a/dev/src/pipelines/expression.ts b/dev/src/pipelines/expression.ts index fb0e2417e..348b17e34 100644 --- a/dev/src/pipelines/expression.ts +++ b/dev/src/pipelines/expression.ts @@ -674,6 +674,334 @@ export abstract class Expression return new FunctionExpression('array_length', [this]); } + /** + * @beta + * Returns the first element of the array. + * + * @example + * ```typescript + * // Get the first element of the 'myArray' field. + * field("myArray").arrayFirst(); + * ``` + * + * @returns A new `Expression` representing the first element. + */ + arrayFirst(): FunctionExpression { + return new FunctionExpression('array_first', [this]); + } + + /** + * @beta + * Returns the first `n` elements of the array. + * + * @example + * ```typescript + * // Get the first 3 elements of the 'myArray' field. + * field("myArray").arrayFirstN(3); + * ``` + * + * @param n The number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ + arrayFirstN(n: number): FunctionExpression; + + /** + * @beta + * Returns the first `n` elements of the array. + * + * @example + * ```typescript + * // Get the first n elements of the 'myArray' field. + * field("myArray").arrayFirstN(field("count")); + * ``` + * + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ + arrayFirstN(n: Expression): FunctionExpression; + arrayFirstN(n: number | Expression): FunctionExpression { + return new FunctionExpression('array_first_n', [ + this, + valueToDefaultExpr(n), + ]); + } + + /** + * @beta + * Returns the last element of the array. + * + * @example + * ```typescript + * // Get the last element of the 'myArray' field. + * field("myArray").arrayLast(); + * ``` + * + * @returns A new `Expression` representing the last element. + */ + arrayLast(): FunctionExpression { + return new FunctionExpression('array_last', [this]); + } + + /** + * @beta + * Returns the last `n` elements of the array. + * + * @example + * ```typescript + * // Get the last 3 elements of the 'myArray' field. + * field("myArray").arrayLastN(3); + * ``` + * + * @param n The number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ + arrayLastN(n: number): FunctionExpression; + + /** + * @beta + * Returns the last `n` elements of the array. + * + * @example + * ```typescript + * // Get the last n elements of the 'myArray' field. + * field("myArray").arrayLastN(field("count")); + * ``` + * + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ + arrayLastN(n: Expression): FunctionExpression; + arrayLastN(n: number | Expression): FunctionExpression { + return new FunctionExpression('array_last_n', [ + this, + valueToDefaultExpr(n), + ]); + } + + /** + * @beta + * Returns the maximum value in the array. + * + * @example + * ```typescript + * // Get the maximum value of the 'myArray' field. + * field("myArray").arrayMaximum(); + * ``` + * + * @returns A new `Expression` representing the maximum value. + */ + arrayMaximum(): FunctionExpression { + return new FunctionExpression('maximum', [this]); + } + + /** + * @beta + * Returns the largest `n` elements of the array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the largest 3 elements of the 'myArray' field. + * field("myArray").arrayMaximumN(3); + * ``` + * + * @param n The number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ + arrayMaximumN(n: number): FunctionExpression; + + /** + * @beta + * Returns the largest `n` elements of the array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the largest n elements of the 'myArray' field. + * field("myArray").arrayMaximumN(field("count")); + * ``` + * + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ + arrayMaximumN(n: Expression): FunctionExpression; + arrayMaximumN(n: number | Expression): FunctionExpression { + return new FunctionExpression('maximum_n', [this, valueToDefaultExpr(n)]); + } + + /** + * @beta + * Returns the minimum value in the array. + * + * @example + * ```typescript + * // Get the minimum value of the 'myArray' field. + * field("myArray").arrayMinimum(); + * ``` + * + * @returns A new `Expression` representing the minimum value. + */ + arrayMinimum(): FunctionExpression { + return new FunctionExpression('minimum', [this]); + } + + /** + * @beta + * Returns the smallest `n` elements of the array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the smallest 3 elements of the 'myArray' field. + * field("myArray").arrayMinimumN(3); + * ``` + * + * @param n The number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ + arrayMinimumN(n: number): FunctionExpression; + + /** + * @beta + * Returns the smallest `n` elements of the array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the smallest n elements of the 'myArray' field. + * field("myArray").arrayMinimumN(field("count")); + * ``` + * + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ + arrayMinimumN(n: Expression): FunctionExpression; + arrayMinimumN(n: number | Expression): FunctionExpression { + return new FunctionExpression('minimum_n', [this, valueToDefaultExpr(n)]); + } + + /** + * @beta + * Returns the first index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the first index of the value 3 in the 'myArray' field. + * field("myArray").arrayIndexOf(3); + * ``` + * + * @param search The value to search for. + * @returns A new `Expression` representing the index. + */ + arrayIndexOf(search: unknown): FunctionExpression; + + /** + * @beta + * Returns the first index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the first index of the value in 'searchVal' field in the 'myArray' field. + * field("myArray").arrayIndexOf(field("searchVal")); + * ``` + * + * @param search An expression evaluating to the value to search for. + * @returns A new `Expression` representing the index. + */ + arrayIndexOf(search: Expression): FunctionExpression; + arrayIndexOf(search: unknown | Expression): FunctionExpression { + return new FunctionExpression('array_index_of', [ + this, + valueToDefaultExpr(search), + valueToDefaultExpr('first'), + ]); + } + + /** + * @beta + * Returns the last index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the last index of the value 3 in the 'myArray' field. + * field("myArray").arrayLastIndexOf(3); + * ``` + * + * @param search The value to search for. + * @returns A new `Expression` representing the index. + */ + arrayLastIndexOf(search: unknown): FunctionExpression; + + /** + * @beta + * Returns the last index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the last index of the value in 'searchVal' field in the 'myArray' field. + * field("myArray").arrayLastIndexOf(field("searchVal")); + * ``` + * + * @param search An expression evaluating to the value to search for. + * @returns A new `Expression` representing the index. + */ + arrayLastIndexOf(search: Expression): FunctionExpression; + arrayLastIndexOf(search: unknown | Expression): FunctionExpression { + return new FunctionExpression('array_index_of', [ + this, + valueToDefaultExpr(search), + valueToDefaultExpr('last'), + ]); + } + + /** + * @beta + * Returns all indices of the search value in the array. + * + * @example + * ```typescript + * // Get all indices of the value 3 in the 'myArray' field. + * field("myArray").arrayIndexOfAll(3); + * ``` + * + * @param search The value to search for. + * @returns A new `Expression` representing the indices. + */ + arrayIndexOfAll(search: unknown): FunctionExpression; + + /** + * @beta + * Returns all indices of the search value in the array. + * + * @example + * ```typescript + * // Get all indices of the value in 'searchVal' field in the 'myArray' field. + * field("myArray").arrayIndexOfAll(field("searchVal")); + * ``` + * + * @param search An expression evaluating to the value to search for. + * @returns A new `Expression` representing the indices. + */ + arrayIndexOfAll(search: Expression): FunctionExpression; + arrayIndexOfAll(search: unknown | Expression): FunctionExpression { + return new FunctionExpression('array_index_of_all', [ + this, + valueToDefaultExpr(search), + ]); + } + /** * @beta * Creates an expression that checks if this expression is equal to any of the provided values or @@ -8743,6 +9071,653 @@ export function type( /** * @beta + * + * Creates an expression that returns the first element of an array. + * + * @example + * ```typescript + * // Get the first tag from the 'tags' array field + * arrayFirst("tags"); + * ``` + * + * @param fieldName The name of the field containing the array. + * @returns A new `Expression` representing the first element. + */ +export function arrayFirst(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first element of an array. + * + * @example + * ```typescript + * // Get the first tag from the 'tags' array field + * arrayFirst(field("tags")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @returns A new `Expression` representing the first element. + */ +export function arrayFirst(arrayExpression: Expression): FunctionExpression; +export function arrayFirst(array: Expression | string): FunctionExpression { + return fieldOrExpression(array).arrayFirst(); +} + +/** + * @beta + * + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first 3 tags from the 'tags' array field + * arrayFirstN("tags", 3); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n The number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ +export function arrayFirstN(fieldName: string, n: number): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first n tags from the 'tags' array field + * arrayFirstN("tags", field("count")); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ +export function arrayFirstN( + fieldName: string, + n: Expression, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first 3 elements from an array expression + * arrayFirstN(field("tags"), 3); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n The number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ +export function arrayFirstN( + arrayExpression: Expression, + n: number, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first n elements from an array expression + * arrayFirstN(field("tags"), field("count")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ +export function arrayFirstN( + arrayExpression: Expression, + n: Expression, +): FunctionExpression; +export function arrayFirstN( + array: Expression | string, + n: Expression | number, +): FunctionExpression { + return fieldOrExpression(array).arrayFirstN(valueToDefaultExpr(n)); +} + +/** + * @beta + * + * Creates an expression that returns the last element of an array. + * + * @example + * ```typescript + * // Get the last tag from the 'tags' array field + * arrayLast("tags"); + * ``` + * + * @param fieldName The name of the field containing the array. + * @returns A new `Expression` representing the last element. + */ +export function arrayLast(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last element of an array. + * + * @example + * ```typescript + * // Get the last tag from the 'tags' array field + * arrayLast(field("tags")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @returns A new `Expression` representing the last element. + */ +export function arrayLast(arrayExpression: Expression): FunctionExpression; +export function arrayLast(array: Expression | string): FunctionExpression { + return fieldOrExpression(array).arrayLast(); +} + +/** + * @beta + * + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last 3 tags from the 'tags' array field + * arrayLastN("tags", 3); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n The number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ +export function arrayLastN(fieldName: string, n: number): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last n tags from the 'tags' array field + * arrayLastN("tags", field("count")); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ +export function arrayLastN( + fieldName: string, + n: Expression, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last 3 elements from an array expression + * arrayLastN(field("tags"), 3); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n The number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ +export function arrayLastN( + arrayExpression: Expression, + n: number, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last n elements from an array expression + * arrayLastN(field("tags"), field("count")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ +export function arrayLastN( + arrayExpression: Expression, + n: Expression, +): FunctionExpression; +export function arrayLastN( + array: Expression | string, + n: Expression | number, +): FunctionExpression { + return fieldOrExpression(array).arrayLastN(valueToDefaultExpr(n)); +} + +/** + * @beta + * + * Creates an expression that returns the maximum value in an array. + * + * @example + * ```typescript + * // Get the maximum value from the 'scores' array field + * arrayMaximum("scores"); + * ``` + * + * @param fieldName The name of the field containing the array. + * @returns A new `Expression` representing the maximum value. + */ +export function arrayMaximum(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the maximum value in an array. + * + * @example + * ```typescript + * // Get the maximum value from the 'scores' array field + * arrayMaximum(field("scores")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @returns A new `Expression` representing the maximum value. + */ +export function arrayMaximum(arrayExpression: Expression): FunctionExpression; +export function arrayMaximum(array: Expression | string): FunctionExpression { + return fieldOrExpression(array).arrayMaximum(); +} + +/** + * @beta + * + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top 3 scores from the 'scores' array field + * arrayMaximumN("scores", 3); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n The number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ +export function arrayMaximumN(fieldName: string, n: number): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top n scores from the 'scores' array field + * arrayMaximumN("scores", field("count")); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ +export function arrayMaximumN( + fieldName: string, + n: Expression, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top 3 elements from an array expression + * arrayMaximumN(field("scores"), 3); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n The number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ +export function arrayMaximumN( + arrayExpression: Expression, + n: number, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top n elements from an array expression + * arrayMaximumN(field("scores"), field("count")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ +export function arrayMaximumN( + arrayExpression: Expression, + n: Expression, +): FunctionExpression; +export function arrayMaximumN( + array: Expression | string, + n: Expression | number, +): FunctionExpression { + return fieldOrExpression(array).arrayMaximumN(valueToDefaultExpr(n)); +} + +/** + * @beta + * + * Creates an expression that returns the minimum value in an array. + * + * @example + * ```typescript + * // Get the minimum value from the 'scores' array field + * arrayMinimum("scores"); + * ``` + * + * @param fieldName The name of the field containing the array. + * @returns A new `Expression` representing the minimum value. + */ +export function arrayMinimum(fieldName: string): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the minimum value in an array. + * + * @example + * ```typescript + * // Get the minimum value from the 'scores' array field + * arrayMinimum(field("scores")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @returns A new `Expression` representing the minimum value. + */ +export function arrayMinimum(arrayExpression: Expression): FunctionExpression; +export function arrayMinimum(array: Expression | string): FunctionExpression { + return fieldOrExpression(array).arrayMinimum(); +} + +/** + * @beta + * + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom 3 scores from the 'scores' array field + * arrayMinimumN("scores", 3); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n The number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ +export function arrayMinimumN(fieldName: string, n: number): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom n scores from the 'scores' array field + * arrayMinimumN(field("scores"), field("count")); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ +export function arrayMinimumN( + fieldName: string, + n: Expression, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom 3 scores from the 'scores' array field + * arrayMinimumN(field("scores"), 3); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n The number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ +export function arrayMinimumN( + arrayExpression: Expression, + n: number, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom n scores from the 'scores' array field + * arrayMinimumN(field("scores"), field("count")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ +export function arrayMinimumN( + arrayExpression: Expression, + n: Expression, +): FunctionExpression; +export function arrayMinimumN( + array: Expression | string, + n: Expression | number, +): FunctionExpression { + return fieldOrExpression(array).arrayMinimumN(valueToDefaultExpr(n)); +} + +/** + * @beta + * + * Creates an expression that returns the first index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the index of "politics" in the 'tags' array field + * arrayIndexOf("tags", "politics"); + * ``` + * + * @param fieldName The name of the field containing the array to search. + * @param search The value to search for. + * @returns A new `Expression` representing the index. + */ +export function arrayIndexOf( + fieldName: string, + search: unknown | Expression, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the first index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the index of "politics" in the 'tags' array field + * arrayIndexOf(field("tags"), "politics"); + * ``` + * + * @param arrayExpression The expression representing the array to search. + * @param search The value to search for. + * @returns A new `Expression` representing the index. + */ +export function arrayIndexOf( + arrayExpression: Expression, + search: unknown | Expression, +): FunctionExpression; +export function arrayIndexOf( + array: Expression | string, + search: unknown | Expression, +): FunctionExpression { + return fieldOrExpression(array).arrayIndexOf(valueToDefaultExpr(search)); +} + +/** + * @beta + * + * Creates an expression that returns the last index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the last index of "politics" in the 'tags' array field + * arrayLastIndexOf("tags", "politics"); + * ``` + * + * @param fieldName The name of the field containing the array to search. + * @param search The value to search for. + * @returns A new `Expression` representing the index. + */ +export function arrayLastIndexOf( + fieldName: string, + search: unknown | Expression, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns the last index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the last index of "politics" in the 'tags' array field + * arrayLastIndexOf(field("tags"), "politics"); + * ``` + * + * @param arrayExpression The expression representing the array to search. + * @param search The value to search for. + * @returns A new `Expression` representing the index. + */ +export function arrayLastIndexOf( + arrayExpression: Expression, + search: unknown | Expression, +): FunctionExpression; +export function arrayLastIndexOf( + array: Expression | string, + search: unknown | Expression, +): FunctionExpression { + return fieldOrExpression(array).arrayLastIndexOf(valueToDefaultExpr(search)); +} + +/** + * @beta + * + * Creates an expression that returns all indices of the search value in an array. + * + * @example + * ```typescript + * // Get all indices of 5 in the 'scores' array field + * arrayIndexOfAll("scores", 5); + * ``` + * + * @param fieldName The name of the field containing the array to search. + * @param search The value to search for. + * @returns A new `Expression` representing the indices. + */ +export function arrayIndexOfAll( + fieldName: string, + search: unknown | Expression, +): FunctionExpression; + +/** + * @beta + * + * Creates an expression that returns all indices of the search value in an array. + * + * @example + * ```typescript + * // Get all indices of 5 in the 'scores' array field + * arrayIndexOfAll(field("scores"), 5); + * ``` + * + * @param arrayExpression The expression representing the array to search. + * @param search The value to search for. + * @returns A new `Expression` representing the indices. + */ +export function arrayIndexOfAll( + arrayExpression: Expression, + search: unknown | Expression, +): FunctionExpression; +export function arrayIndexOfAll( + array: Expression | string, + search: unknown | Expression, +): FunctionExpression { + return fieldOrExpression(array).arrayIndexOfAll(valueToDefaultExpr(search)); +} + +/** + * @beta + * * Creates an expression that checks if the value in the specified field is of the given type. * * @remarks Null or undefined fields evaluate to skip/error. Use `ifAbsent()` / `isAbsent()` to evaluate missing data. diff --git a/dev/src/pipelines/index.ts b/dev/src/pipelines/index.ts index 012a8fbc8..ef003ec0a 100644 --- a/dev/src/pipelines/index.ts +++ b/dev/src/pipelines/index.ts @@ -56,6 +56,17 @@ export { equalAny, map, array, + arrayFirst, + arrayLast, + arrayFirstN, + arrayLastN, + arrayIndexOf, + arrayIndexOfAll, + arrayLastIndexOf, + arrayMaximum, + arrayMinimum, + arrayMaximumN, + arrayMinimumN, field, xor, AggregateFunction, diff --git a/dev/system-test/pipeline.ts b/dev/system-test/pipeline.ts index a584a9b14..9f1383653 100644 --- a/dev/system-test/pipeline.ts +++ b/dev/system-test/pipeline.ts @@ -73,6 +73,17 @@ import { arrayContains, arrayContainsAny, arrayReverse, + arrayFirst, + arrayFirstN, + arrayIndexOf, + arrayIndexOfAll, + arrayLast, + arrayLastIndexOf, + arrayLastN, + arrayMaximum, + arrayMaximumN, + arrayMinimum, + arrayMinimumN, average, countAll, endsWith, @@ -3264,6 +3275,550 @@ describe.skipClassic('Pipeline class', () => { expectResults(snapshot, ...expectedResults); }); + it('supports arrayFirst', async () => { + let snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayFirst('tags').as('firstTag')) + .execute(); + const expectedResults = [ + { + firstTag: 'adventure', + }, + { + firstTag: 'politics', + }, + { + firstTag: 'classic', + }, + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayFirst().as('firstTag')) + .execute(); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + }), + ) + .select( + arrayFirst('empty').as('emptyResult'), + arrayFirst('nullVal').as('nullResult'), + arrayFirst('nonExistent').as('absentResult'), + ) + .execute(); + + expectResults(snapshot, { + // no emptyResult because arrayFirst returns UNSET for empty arrays + nullResult: null, + absentResult: null, + }); + }); + + it('supports arrayFirstN', async () => { + let snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayFirstN('tags', 2).as('firstTwoTags')) + .execute(); + const expectedResults = [ + { + firstTwoTags: ['adventure', 'magic'], + }, + { + firstTwoTags: ['politics', 'desert'], + }, + { + firstTwoTags: ['classic', 'social commentary'], + }, + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayFirstN(2).as('firstTwoTags')) + .execute(); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + }), + ) + .select( + arrayFirstN('empty', 1).as('emptyResult'), + arrayFirstN('nullVal', 1).as('nullResult'), + arrayFirstN('nonExistent', 1).as('absentResult'), + ) + .execute(); + + expectResults(snapshot, { + emptyResult: [], + nullResult: null, + absentResult: null, + }); + }); + + it('supports arrayLast', async () => { + let snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayLast('tags').as('lastTag')) + .execute(); + const expectedResults = [ + { + lastTag: 'epic', + }, + { + lastTag: 'ecology', + }, + { + lastTag: 'love', + }, + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayLast().as('lastTag')) + .execute(); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + }), + ) + .select( + arrayLast('empty').as('emptyResult'), + arrayLast('nullVal').as('nullResult'), + arrayLast('nonExistent').as('absentResult'), + ) + .execute(); + + expectResults(snapshot, { + // no emptyResult because arrayLast returns UNSET for empty arrays + nullResult: null, + absentResult: null, + }); + }); + + it('supports arrayLastN', async () => { + let snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(arrayLastN('tags', 2).as('lastTwoTags')) + .execute(); + const expectedResults = [ + { + lastTwoTags: ['magic', 'epic'], + }, + { + lastTwoTags: ['desert', 'ecology'], + }, + { + lastTwoTags: ['social commentary', 'love'], + }, + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(3) + .select(field('tags').arrayLastN(2).as('lastTwoTags')) + .execute(); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + }), + ) + .select( + arrayLastN('empty', 1).as('emptyResult'), + arrayLastN('nullVal', 1).as('nullResult'), + arrayLastN('nonExistent', 1).as('absentResult'), + ) + .execute(); + + expectResults(snapshot, { + emptyResult: [], + nullResult: null, + absentResult: null, + }); + }); + + it('supports arrayMaximum', async () => { + let snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMaximum('tags').as('maxTag')) + .execute(); + const expectedResults = [ + { + maxTag: 'magic', + }, + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMaximum().as('maxTag')) + .execute(); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent and mixed types + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + mixed: [1, '2', 3, '10'], // string > number in Firestore + }), + ) + .select( + arrayMaximum('empty').as('emptyResult'), + arrayMaximum('nullVal').as('nullResult'), + arrayMaximum('nonExistent').as('absentResult'), + arrayMaximum('mixed').as('mixedResult'), + ) + .execute(); + + expectResults(snapshot, { + emptyResult: null, + nullResult: null, + absentResult: null, + mixedResult: '2', // "2" > "10" > 3 > 1 + }); + }); + + it('supports arrayMaximumN', async () => { + let snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMaximumN('tags', 2).as('maxTwoTags')) + .execute(); + const expectedResults = [ + { + maxTwoTags: ['magic', 'epic'], + }, + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMaximumN(2).as('maxTwoTags')) + .execute(); + expectResults(snapshot, ...expectedResults); + }); + + it('supports arrayMinimum', async () => { + let snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMinimum('tags').as('minTag')) + .execute(); + const expectedResults = [ + { + minTag: 'adventure', + }, + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMinimum().as('minTag')) + .execute(); + expectResults(snapshot, ...expectedResults); + + // Test with empty/null/non-existent and mixed types + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + empty: [], + nullVal: null, + mixed: [1, '2', 3, '10'], // Strings > Numbers in Firestore + }), + ) + .select( + arrayMinimum('empty').as('emptyResult'), + arrayMinimum('nullVal').as('nullResult'), + arrayMinimum('nonExistent').as('absentResult'), + arrayMinimum('mixed').as('mixedResult'), + ) + .execute(); + + expectResults(snapshot, { + emptyResult: null, + nullResult: null, + absentResult: null, + mixedResult: 1, // 1 < 2 < 3 < "10" + }); + }); + + it('supports arrayMinimumN', async () => { + let snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(arrayMinimumN('tags', 2).as('minTwoTags')) + .execute(); + const expectedResults = [ + { + minTwoTags: ['adventure', 'epic'], + }, + ]; + expectResults(snapshot, ...expectedResults); + + snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select(field('tags').arrayMinimumN(2).as('minTwoTags')) + .execute(); + expectResults(snapshot, ...expectedResults); + }); + + it('supports arrayIndexOf', async () => { + const snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + arrayIndexOf('tags', 'adventure').as('indexFirst'), + arrayIndexOf(field('tags'), 'magic').as('indexSecond'), + field('tags').arrayIndexOf('adventure').as('indexFirst2'), + arrayIndexOf('tags', 'nonexistent').as('indexNone'), + arrayIndexOf('empty', 'anything').as('indexEmpty'), + ) + .execute(); + const expectedResults = [ + { + indexFirst: 0, + indexSecond: 1, + indexFirst2: 0, + indexNone: -1, + indexEmpty: null, + }, + ]; + expectResults(snapshot, ...expectedResults); + + // Test with duplicate values + const snapshotDuplicates = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 2, 3, 2, 1], + }), + ) + .select(arrayIndexOf('arr', 2).as('firstIndex')) + .execute(); + expectResults(snapshotDuplicates, { + firstIndex: 1, + }); + + // Test with null values + const snapshotNull = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, null, 3, null, 1], + nullArr: null, + }), + ) + .select( + arrayIndexOf('arr', null).as('firstNullIndex'), + arrayIndexOf('nullArr', 1).as('nullArrIndex'), + ) + .execute(); + expectResults(snapshotNull, { + firstNullIndex: 1, + nullArrIndex: null, + }); + }); + + it('supports arrayLastIndexOf', async () => { + const snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + arrayLastIndexOf('tags', 'adventure').as('lastIndexFirst'), + arrayLastIndexOf(field('tags'), 'epic').as('lastIndexLast'), + field('tags').arrayLastIndexOf('adventure').as('lastIndexFirst2'), + arrayLastIndexOf('tags', 'nonexistent').as('lastIndexNone'), + arrayLastIndexOf('empty', 'anything').as('lastIndexEmpty'), + ) + .execute(); + const expectedResults = [ + { + lastIndexFirst: 0, + lastIndexLast: 2, + lastIndexFirst2: 0, + lastIndexNone: -1, + lastIndexEmpty: null, + }, + ]; + expectResults(snapshot, ...expectedResults); + + // Test with duplicate values + const snapshotDuplicates = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 2, 3, 2, 1], + }), + ) + .select(arrayLastIndexOf('arr', 2).as('lastIndex')) + .execute(); + expectResults(snapshotDuplicates, { + lastIndex: 3, + }); + }); + + it('supports arrayIndexOfAll', async () => { + const snapshot = await firestore + .pipeline() + .collection(randomCol.path) + .sort(field('rating').descending()) + .limit(1) + .select( + arrayIndexOfAll('tags', 'adventure').as('indicesFirst'), + arrayIndexOfAll(field('tags'), 'epic').as('indicesLast'), + field('tags').arrayIndexOfAll('nonexistent').as('indicesNone'), + arrayIndexOfAll('empty', 'anything').as('indicesEmpty'), + ) + .execute(); + const expectedResults = [ + { + indicesFirst: [0], + indicesLast: [2], + indicesNone: [], + indicesEmpty: null, + }, + ]; + expectResults(snapshot, ...expectedResults); + + // Test with duplicate values + const snapshotDuplicates = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, 2, 3, 2, 1], + }), + ) + .select( + arrayIndexOfAll('arr', 1).as('indices1'), + arrayIndexOfAll('arr', 2).as('indices2'), + ) + .execute(); + expectResults(snapshotDuplicates, { + indices1: [0, 4], + indices2: [1, 3], + }); + + // Test with null values + const snapshotNull = await firestore + .pipeline() + .collection(randomCol.path) + .limit(1) + .replaceWith( + map({ + arr: [1, null, 3, null, 1], + nullArr: null, + }), + ) + .select( + arrayIndexOfAll('arr', null).as('nullIndices'), + arrayIndexOfAll('nullArr', null).as('nullArrIndices'), + ) + .execute(); + expectResults(snapshotNull, { + nullIndices: [1, 3], + nullArrIndices: null, + }); + }); + it('supports map', async () => { const snapshot = await firestore .pipeline() diff --git a/types/firestore.d.ts b/types/firestore.d.ts index 7c2c44ea1..e0f56d4af 100644 --- a/types/firestore.d.ts +++ b/types/firestore.d.ts @@ -3631,6 +3631,288 @@ declare namespace FirebaseFirestore { */ arrayLength(): FunctionExpression; + /** + * @beta + * Returns the first element of the array. + * + * @example + * ```typescript + * // Get the first element of the 'myArray' field. + * field("myArray").arrayFirst(); + * ``` + * + * @returns A new `Expression` representing the first element. + */ + arrayFirst(): FunctionExpression; + + /** + * @beta + * Returns the first `n` elements of the array. + * + * @example + * ```typescript + * // Get the first 3 elements of the 'myArray' field. + * field("myArray").arrayFirstN(3); + * ``` + * + * @param n The number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ + arrayFirstN(n: number): FunctionExpression; + + /** + * @beta + * Returns the first `n` elements of the array. + * + * @example + * ```typescript + * // Get the first n elements of the 'myArray' field. + * field("myArray").arrayFirstN(field("count")); + * ``` + * + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the first `n` elements. + */ + arrayFirstN(n: Expression): FunctionExpression; + + /** + * @beta + * Returns the last element of the array. + * + * @example + * ```typescript + * // Get the last element of the 'myArray' field. + * field("myArray").arrayLast(); + * ``` + * + * @returns A new `Expression` representing the last element. + */ + arrayLast(): FunctionExpression; + + /** + * @beta + * Returns the last `n` elements of the array. + * + * @example + * ```typescript + * // Get the last 3 elements of the 'myArray' field. + * field("myArray").arrayLastN(3); + * ``` + * + * @param n The number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ + arrayLastN(n: number): FunctionExpression; + + /** + * @beta + * Returns the last `n` elements of the array. + * + * @example + * ```typescript + * // Get the last n elements of the 'myArray' field. + * field("myArray").arrayLastN(field("count")); + * ``` + * + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the last `n` elements. + */ + arrayLastN(n: Expression): FunctionExpression; + + /** + * @beta + * Returns the maximum value in the array. + * + * @example + * ```typescript + * // Get the maximum value of the 'myArray' field. + * field("myArray").arrayMaximum(); + * ``` + * + * @returns A new `Expression` representing the maximum value. + */ + arrayMaximum(): FunctionExpression; + + /** + * @beta + * Returns the largest `n` elements of the array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the largest 3 elements of the 'myArray' field. + * field("myArray").arrayMaximumN(3); + * ``` + * + * @param n The number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ + arrayMaximumN(n: number): FunctionExpression; + + /** + * @beta + * Returns the largest `n` elements of the array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the largest n elements of the 'myArray' field. + * field("myArray").arrayMaximumN(field("count")); + * ``` + * + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the largest `n` elements. + */ + arrayMaximumN(n: Expression): FunctionExpression; + + /** + * @beta + * Returns the minimum value in the array. + * + * @example + * ```typescript + * // Get the minimum value of the 'myArray' field. + * field("myArray").arrayMinimum(); + * ``` + * + * @returns A new `Expression` representing the minimum value. + */ + arrayMinimum(): FunctionExpression; + + /** + * @beta + * Returns the smallest `n` elements of the array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the smallest 3 elements of the 'myArray' field. + * field("myArray").arrayMinimumN(3); + * ``` + * + * @param n The number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ + arrayMinimumN(n: number): FunctionExpression; + + /** + * @beta + * Returns the smallest `n` elements of the array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the smallest n elements of the 'myArray' field. + * field("myArray").arrayMinimumN(field("count")); + * ``` + * + * @param n An expression evaluating to the number of elements to return. + * @returns A new `Expression` representing the smallest `n` elements. + */ + arrayMinimumN(n: Expression): FunctionExpression; + + /** + * @beta + * Returns the first index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the first index of the value 3 in the 'myArray' field. + * field("myArray").arrayIndexOf(3); + * ``` + * + * @param search The value to search for. + * @returns A new `Expression` representing the index. + */ + arrayIndexOf(search: unknown): FunctionExpression; + + /** + * @beta + * Returns the first index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the first index of the value in 'searchVal' field in the 'myArray' field. + * field("myArray").arrayIndexOf(field("searchVal")); + * ``` + * + * @param search An expression evaluating to the value to search for. + * @returns A new `Expression` representing the index. + */ + arrayIndexOf(search: Expression): FunctionExpression; + + /** + * @beta + * Returns the last index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the last index of the value 3 in the 'myArray' field. + * field("myArray").arrayLastIndexOf(3); + * ``` + * + * @param search The value to search for. + * @returns A new `Expression` representing the index. + */ + arrayLastIndexOf(search: unknown): FunctionExpression; + + /** + * @beta + * Returns the last index of the search value in the array, or -1 if not found. + * + * @example + * ```typescript + * // Get the last index of the value in 'searchVal' field in the 'myArray' field. + * field("myArray").arrayLastIndexOf(field("searchVal")); + * ``` + * + * @param search An expression evaluating to the value to search for. + * @returns A new `Expression` representing the index. + */ + arrayLastIndexOf(search: Expression): FunctionExpression; + + /** + * @beta + * Returns all indices of the search value in the array. + * + * @example + * ```typescript + * // Get all indices of the value 3 in the 'myArray' field. + * field("myArray").arrayIndexOfAll(3); + * ``` + * + * @param search The value to search for. + * @returns A new `Expression` representing the indices. + */ + arrayIndexOfAll(search: unknown): FunctionExpression; + + /** + * @beta + * Returns all indices of the search value in the array. + * + * @example + * ```typescript + * // Get all indices of the value in 'searchVal' field in the 'myArray' field. + * field("myArray").arrayIndexOfAll(field("searchVal")); + * ``` + * + * @param search An expression evaluating to the value to search for. + * @returns A new `Expression` representing the indices. + */ + arrayIndexOfAll(search: Expression): FunctionExpression; + /** * @beta * Creates an expression that checks if this expression is equal to any of the provided values or @@ -7295,6 +7577,557 @@ declare namespace FirebaseFirestore { * @returns A new {@code Expression} representing the length of the array. */ export function arrayLength(array: Expression): FunctionExpression; + + /** + * @beta + * Creates an expression that returns the first element of an array. + * + * @example + * ```typescript + * // Get the first tag from the 'tags' array field + * arrayFirst("tags"); + * ``` + * + * @param fieldName The name of the field containing the array. + * @returns A new {@code Expression} representing the first element. + */ + export function arrayFirst(fieldName: string): FunctionExpression; + /** + * @beta + * Creates an expression that returns the first element of an array. + * + * @example + * ```typescript + * // Get the first tag from the 'tags' array field + * arrayFirst(field("tags")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @returns A new {@code Expression} representing the first element. + */ + export function arrayFirst(arrayExpression: Expression): FunctionExpression; + /** + * @beta + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first 3 tags from the 'tags' array field + * arrayFirstN("tags", 3); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n The number of elements to return. + * @returns A new {@code Expression} representing the first `n` elements. + */ + export function arrayFirstN( + fieldName: string, + n: number, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first n tags from the 'tags' array field + * arrayFirstN("tags", field("count")); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new {@code Expression} representing the first `n` elements. + */ + export function arrayFirstN( + fieldName: string, + n: Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first 3 elements from an array expression + * arrayFirstN(field("tags"), 3); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n The number of elements to return. + * @returns A new {@code Expression} representing the first `n` elements. + */ + export function arrayFirstN( + arrayExpression: Expression, + n: number, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the first `n` elements of an array. + * + * @example + * ```typescript + * // Get the first n elements from an array expression + * arrayFirstN(field("tags"), field("count")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new {@code Expression} representing the first `n` elements. + */ + export function arrayFirstN( + arrayExpression: Expression, + n: Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that indexes into an array from the beginning or end + * and return the element. If the offset exceeds the array length, an error is + * returned. A negative offset, starts from the end. + * + * @example + * ```typescript + * // Return the value in the tags field array at index 1. + * arrayGet(field('tags'), 1); + * ``` + * + * @param arrayExpression An `Expression` evaluating to an array. + * @param offset The index of the element to return. + * @returns A new `Expression` representing the 'arrayGet' operation. + */ + export function arrayIndexOf( + fieldName: string, + search: unknown | Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the first index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the index of "politics" in the 'tags' array field + * arrayIndexOf(field("tags"), "politics"); + * ``` + * + * @param arrayExpression The expression representing the array to search. + * @param search The value to search for. + * @returns A new {@code Expression} representing the index. + */ + export function arrayIndexOf( + arrayExpression: Expression, + search: unknown | Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns all indices of the search value in an array. + * + * @example + * ```typescript + * // Get all indices of 5 in the 'scores' array field + * arrayIndexOfAll("scores", 5); + * ``` + * + * @param fieldName The name of the field containing the array to search. + * @param search The value to search for. + * @returns A new {@code Expression} representing the indices. + */ + export function arrayIndexOfAll( + fieldName: string, + search: unknown | Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns all indices of the search value in an array. + * + * @example + * ```typescript + * // Get all indices of 5 in the 'scores' array field + * arrayIndexOfAll(field("scores"), 5); + * ``` + * + * @param arrayExpression The expression representing the array to search. + * @param search The value to search for. + * @returns A new {@code Expression} representing the indices. + */ + export function arrayIndexOfAll( + arrayExpression: Expression, + search: unknown | Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the last element of an array. + * + * @example + * ```typescript + * // Get the last tag from the 'tags' array field + * arrayLast("tags"); + * ``` + * + * @param fieldName The name of the field containing the array. + * @returns A new {@code Expression} representing the last element. + */ + export function arrayLast(fieldName: string): FunctionExpression; + /** + * @beta + * Creates an expression that returns the last element of an array. + * + * @example + * ```typescript + * // Get the last tag from the 'tags' array field + * arrayLast(field("tags")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @returns A new {@code Expression} representing the last element. + */ + export function arrayLast(arrayExpression: Expression): FunctionExpression; + /** + * @beta + * Creates an expression that returns the last index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the last index of "politics" in the 'tags' array field + * arrayLastIndexOf("tags", "politics"); + * ``` + * + * @param fieldName The name of the field containing the array to search. + * @param search The value to search for. + * @returns A new {@code Expression} representing the index. + */ + export function arrayLastIndexOf( + fieldName: string, + search: unknown | Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the last index of the search value in an array. + * Returns -1 if the value is not found. + * + * @example + * ```typescript + * // Get the last index of "politics" in the 'tags' array field + * arrayLastIndexOf(field("tags"), "politics"); + * ``` + * + * @param arrayExpression The expression representing the array to search. + * @param search The value to search for. + * @returns A new {@code Expression} representing the index. + */ + export function arrayLastIndexOf( + arrayExpression: Expression, + search: unknown | Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last 3 tags from the 'tags' array field + * arrayLastN("tags", 3); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n The number of elements to return. + * @returns A new {@code Expression} representing the last `n` elements. + */ + export function arrayLastN( + fieldName: string, + n: number, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last n tags from the 'tags' array field + * arrayLastN("tags", field("count")); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new {@code Expression} representing the last `n` elements. + */ + export function arrayLastN( + fieldName: string, + n: Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last 3 elements from an array expression + * arrayLastN(field("tags"), 3); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n The number of elements to return. + * @returns A new {@code Expression} representing the last `n` elements. + */ + export function arrayLastN( + arrayExpression: Expression, + n: number, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the last `n` elements of an array. + * + * @example + * ```typescript + * // Get the last n elements from an array expression + * arrayLastN(field("tags"), field("count")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new {@code Expression} representing the last `n` elements. + */ + export function arrayLastN( + arrayExpression: Expression, + n: Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the maximum value in an array. + * + * @example + * ```typescript + * // Get the maximum value from the 'scores' array field + * arrayMaximum("scores"); + * ``` + * + * @param fieldName The name of the field containing the array. + * @returns A new {@code Expression} representing the maximum value. + */ + export function arrayMaximum(fieldName: string): FunctionExpression; + /** + * @beta + * Creates an expression that returns the maximum value in an array. + * + * @example + * ```typescript + * // Get the maximum value from the 'scores' array field + * arrayMaximum(field("scores")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @returns A new {@code Expression} representing the maximum value. + */ + export function arrayMaximum( + arrayExpression: Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top 3 scores from the 'scores' array field + * arrayMaximumN("scores", 3); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n The number of elements to return. + * @returns A new {@code Expression} representing the largest `n` elements. + */ + export function arrayMaximumN( + fieldName: string, + n: number, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top n scores from the 'scores' array field + * arrayMaximumN("scores", field("count")); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new {@code Expression} representing the largest `n` elements. + */ + export function arrayMaximumN( + fieldName: string, + n: Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top 3 elements from an array expression + * arrayMaximumN(field("scores"), 3); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n The number of elements to return. + * @returns A new {@code Expression} representing the largest `n` elements. + */ + export function arrayMaximumN( + arrayExpression: Expression, + n: number, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the largest `n` elements of an array. + * + * Note: Returns the n largest non-null elements in the array, in descending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the top n elements from an array expression + * arrayMaximumN(field("scores"), field("count")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new {@code Expression} representing the largest `n` elements. + */ + export function arrayMaximumN( + arrayExpression: Expression, + n: Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the minimum value in an array. + * + * @example + * ```typescript + * // Get the minimum value from the 'scores' array field + * arrayMinimum("scores"); + * ``` + * + * @param fieldName The name of the field containing the array. + * @returns A new {@code Expression} representing the minimum value. + */ + export function arrayMinimum(fieldName: string): FunctionExpression; + /** + * @beta + * Creates an expression that returns the minimum value in an array. + * + * @example + * ```typescript + * // Get the minimum value from the 'scores' array field + * arrayMinimum(field("scores")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @returns A new {@code Expression} representing the minimum value. + */ + export function arrayMinimum( + arrayExpression: Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom 3 scores from the 'scores' array field + * arrayMinimumN("scores", 3); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n The number of elements to return. + * @returns A new {@code Expression} representing the smallest `n` elements. + */ + export function arrayMinimumN( + fieldName: string, + n: number, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom n scores from the 'scores' array field + * arrayMinimumN(field("scores"), field("count")); + * ``` + * + * @param fieldName The name of the field containing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new {@code Expression} representing the smallest `n` elements. + */ + export function arrayMinimumN( + fieldName: string, + n: Expression, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom 3 scores from the 'scores' array field + * arrayMinimumN(field("scores"), 3); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n The number of elements to return. + * @returns A new {@code Expression} representing the smallest `n` elements. + */ + export function arrayMinimumN( + arrayExpression: Expression, + n: number, + ): FunctionExpression; + /** + * @beta + * Creates an expression that returns the smallest `n` elements of an array. + * + * Note: Returns the n smallest non-null elements in the array, in ascending + * order. This does not use a stable sort, meaning the order of equivalent + * elements is undefined. + * + * @example + * ```typescript + * // Get the bottom n scores from the 'scores' array field + * arrayMinimumN(field("scores"), field("count")); + * ``` + * + * @param arrayExpression The expression representing the array. + * @param n An expression evaluating to the number of elements to return. + * @returns A new {@code Expression} representing the smallest `n` elements. + */ + export function arrayMinimumN( + arrayExpression: Expression, + n: Expression, + ): FunctionExpression; + /** * @beta * Creates an expression that checks if an expression, when evaluated, is equal to any of the provided values or