@google-cloud/firestore
Version:
Firestore Client Library for Node.js
1,437 lines • 120 kB
JavaScript
"use strict";
// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.Ordering = exports.VariableExpression = exports.BooleanField = exports.BooleanConstant = exports.BooleanFunctionExpression = exports.BooleanExpression = exports.SnippetExpression = exports.FunctionExpression = exports.MapValue = exports.Constant = exports.Field = exports.AliasedExpression = exports.AliasedAggregate = exports.AggregateFunction = exports.Expression = void 0;
exports.field = field;
exports.constant = constant;
exports._constant = _constant;
exports.countIf = countIf;
exports.arrayGet = arrayGet;
exports.isError = isError;
exports.ifError = ifError;
exports.isAbsent = isAbsent;
exports.mapRemove = mapRemove;
exports.mapMerge = mapMerge;
exports.documentId = documentId;
exports.parent = parent;
exports.substring = substring;
exports.add = add;
exports.subtract = subtract;
exports.multiply = multiply;
exports.divide = divide;
exports.mod = mod;
exports.map = map;
exports._mapValue = _mapValue;
exports.array = array;
exports.equal = equal;
exports.notEqual = notEqual;
exports.lessThan = lessThan;
exports.lessThanOrEqual = lessThanOrEqual;
exports.greaterThan = greaterThan;
exports.greaterThanOrEqual = greaterThanOrEqual;
exports.arrayConcat = arrayConcat;
exports.arrayContains = arrayContains;
exports.arrayContainsAny = arrayContainsAny;
exports.arrayContainsAll = arrayContainsAll;
exports.arrayLength = arrayLength;
exports.equalAny = equalAny;
exports.notEqualAny = notEqualAny;
exports.xor = xor;
exports.conditional = conditional;
exports.not = not;
exports.logicalMaximum = logicalMaximum;
exports.logicalMinimum = logicalMinimum;
exports.exists = exists;
exports.reverse = reverse;
exports.arrayFilter = arrayFilter;
exports.arrayTransform = arrayTransform;
exports.arrayTransformWithIndex = arrayTransformWithIndex;
exports.arraySlice = arraySlice;
exports.arrayReverse = arrayReverse;
exports.byteLength = byteLength;
exports.exp = exp;
exports.ceil = ceil;
exports.floor = floor;
exports.countDistinct = countDistinct;
exports.charLength = charLength;
exports.like = like;
exports.regexContains = regexContains;
exports.regexFind = regexFind;
exports.regexFindAll = regexFindAll;
exports.regexMatch = regexMatch;
exports.stringContains = stringContains;
exports.startsWith = startsWith;
exports.endsWith = endsWith;
exports.toLower = toLower;
exports.toUpper = toUpper;
exports.trim = trim;
exports.ltrim = ltrim;
exports.rtrim = rtrim;
exports.stringConcat = stringConcat;
exports.stringIndexOf = stringIndexOf;
exports.stringRepeat = stringRepeat;
exports.stringReplaceAll = stringReplaceAll;
exports.stringReplaceOne = stringReplaceOne;
exports.mapGet = mapGet;
exports.mapSet = mapSet;
exports.mapKeys = mapKeys;
exports.mapValues = mapValues;
exports.mapEntries = mapEntries;
exports.countAll = countAll;
exports.count = count;
exports.sum = sum;
exports.average = average;
exports.minimum = minimum;
exports.maximum = maximum;
exports.first = first;
exports.last = last;
exports.arrayAgg = arrayAgg;
exports.arrayAggDistinct = arrayAggDistinct;
exports.cosineDistance = cosineDistance;
exports.dotProduct = dotProduct;
exports.euclideanDistance = euclideanDistance;
exports.vectorLength = vectorLength;
exports.unixMicrosToTimestamp = unixMicrosToTimestamp;
exports.timestampToUnixMicros = timestampToUnixMicros;
exports.unixMillisToTimestamp = unixMillisToTimestamp;
exports.timestampToUnixMillis = timestampToUnixMillis;
exports.unixSecondsToTimestamp = unixSecondsToTimestamp;
exports.timestampToUnixSeconds = timestampToUnixSeconds;
exports.timestampAdd = timestampAdd;
exports.timestampSubtract = timestampSubtract;
exports.currentTimestamp = currentTimestamp;
exports.and = and;
exports.or = or;
exports.nor = nor;
exports.switchOn = switchOn;
exports.pow = pow;
exports.rand = rand;
exports.round = round;
exports.trunc = trunc;
exports.collectionId = collectionId;
exports.length = length;
exports.ln = ln;
exports.sqrt = sqrt;
exports.stringReverse = stringReverse;
exports.concat = concat;
exports.abs = abs;
exports.ifAbsent = ifAbsent;
exports.ifNull = ifNull;
exports.coalesce = coalesce;
exports.join = join;
exports.log10 = log10;
exports.arraySum = arraySum;
exports.split = split;
exports.timestampTruncate = timestampTruncate;
exports.timestampDiff = timestampDiff;
exports.timestampExtract = timestampExtract;
exports.type = type;
exports.arrayFirst = arrayFirst;
exports.arrayFirstN = arrayFirstN;
exports.arrayLast = arrayLast;
exports.arrayLastN = arrayLastN;
exports.arrayMaximum = arrayMaximum;
exports.arrayMaximumN = arrayMaximumN;
exports.arrayMinimum = arrayMinimum;
exports.arrayMinimumN = arrayMinimumN;
exports.arrayIndexOf = arrayIndexOf;
exports.arrayLastIndexOf = arrayLastIndexOf;
exports.arrayIndexOfAll = arrayIndexOfAll;
exports.isType = isType;
exports.getField = getField;
exports.variable = variable;
exports.currentDocument = currentDocument;
exports.pipelineValue = pipelineValue;
exports.documentMatches = documentMatches;
exports.score = score;
exports.geoDistance = geoDistance;
exports.ascending = ascending;
exports.descending = descending;
const path_1 = require("../path");
const pipeline_util_1 = require("./pipeline-util");
const serializer_1 = require("../serializer");
const util_1 = require("../util");
const options_util_1 = require("./options-util");
/**
* Represents an expression that can be evaluated to a value within the execution of a `Pipeline`.
*
* Expressions are the building blocks for creating complex queries and transformations in
* Firestore pipelines. They can represent:
*
* - **Field references:** Access values from document fields.
* - **Literals:** Represent constant values (strings, numbers, booleans).
* - **Function calls:** Apply functions to one or more expressions.
*
* The `Expression` class provides a fluent API for building expressions. You can chain together
* method calls to create complex expressions.
*/
class Expression {
/**
* @internal
* @private
* Indicates if this expression was created from a literal value passed
* by the caller.
*/
_createdFromLiteral = false;
_protoValueType = 'ProtoValue';
/**
* Creates an expression that adds this expression to another expression.
*
* @example
* ```typescript
* // Add the value of the 'quantity' field and the 'reserve' field.
* field("quantity").add(field("reserve"));
* ```
*
* @param second The expression or literal to add to this expression.
* @param others Optional additional expressions or literals to add to this expression.
* @returns A new `Expression` representing the addition operation.
*/
add(second, ...others) {
const values = [second, ...others];
return new FunctionExpression('add', [
this,
...values.map(value => (0, pipeline_util_1.valueToDefaultExpr)(value)),
]);
}
/**
* Wraps the expression in a [BooleanExpression].
*
* @returns A `BooleanExpression` representing the same expression.
*/
asBoolean() {
if (this instanceof BooleanExpression) {
return this;
}
else if (this instanceof Constant) {
return new BooleanConstant(this);
}
else if (this instanceof Field) {
return new BooleanField(this);
}
else if (this instanceof FunctionExpression) {
return new BooleanFunctionExpression(this);
}
else {
throw new Error(`Conversion of type ${typeof this} to BooleanExpression not supported.`);
}
}
subtract(subtrahend) {
return new FunctionExpression('subtract', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(subtrahend),
]);
}
/**
* Creates an expression that multiplies this expression by another expression.
*
* @example
* ```typescript
* // Multiply the 'quantity' field by the 'price' field
* field("quantity").multiply(field("price"));
* ```
*
* @param second The second expression or literal to multiply by.
* @param others Optional additional expressions or literals to multiply by.
* @returns A new `Expression` representing the multiplication operation.
*/
multiply(second, ...others) {
return new FunctionExpression('multiply', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(second),
...others.map(value => (0, pipeline_util_1.valueToDefaultExpr)(value)),
]);
}
divide(divisor) {
return new FunctionExpression('divide', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(divisor),
]);
}
mod(other) {
return new FunctionExpression('mod', [this, (0, pipeline_util_1.valueToDefaultExpr)(other)]);
}
equal(other) {
return new FunctionExpression('equal', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(other),
]).asBoolean();
}
notEqual(other) {
return new FunctionExpression('not_equal', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(other),
]).asBoolean();
}
lessThan(other) {
return new FunctionExpression('less_than', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(other),
]).asBoolean();
}
lessThanOrEqual(other) {
return new FunctionExpression('less_than_or_equal', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(other),
]).asBoolean();
}
greaterThan(other) {
return new FunctionExpression('greater_than', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(other),
]).asBoolean();
}
greaterThanOrEqual(other) {
return new FunctionExpression('greater_than_or_equal', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(other),
]).asBoolean();
}
/**
* Creates an expression that concatenates an array expression with one or more other arrays.
*
* @example
* ```typescript
* // Combine the 'items' array with another array field.
* field("items").arrayConcat(field("otherItems"));
* ```
* @param secondArray Second array expression or array literal to concatenate.
* @param otherArrays Optional additional array expressions or array literals to concatenate.
* @returns A new `Expr` representing the concatenated array.
*/
arrayConcat(secondArray, ...otherArrays) {
const elements = [secondArray, ...otherArrays];
const exprValues = elements.map(value => (0, pipeline_util_1.valueToDefaultExpr)(value));
return new FunctionExpression('array_concat', [this, ...exprValues]);
}
arrayContains(element) {
return new FunctionExpression('array_contains', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(element),
]).asBoolean();
}
arrayContainsAll(values) {
const normalizedExpr = Array.isArray(values)
? new ListOfExprs(values.map(pipeline_util_1.valueToDefaultExpr))
: (0, util_1.cast)(values);
return new FunctionExpression('array_contains_all', [
this,
normalizedExpr,
]).asBoolean();
}
arrayContainsAny(values) {
const normalizedExpr = Array.isArray(values)
? new ListOfExprs(values.map(pipeline_util_1.valueToDefaultExpr))
: (0, util_1.cast)(values);
return new FunctionExpression('array_contains_any', [
this,
normalizedExpr,
]).asBoolean();
}
/**
* Creates an expression that filters an array using a provided alias and predicate expression.
*
* @example
* ```typescript
* // Filter "scores" to include only values greater than 50
* field("scores").arrayFilter("score", greaterThan(variable("score"), 50));
* ```
*
* @param alias The variable name to use for each element.
* @param filter The predicate boolean expression to evaluate for each element.
* @returns A new `Expression` representing the filtered array.
*/
arrayFilter(alias, filter) {
return new FunctionExpression('array_filter', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(alias),
filter,
]);
}
/**
* Creates an expression that applies a provided transformation to each element in an array.
*
* @example
* ```typescript
* // Transform the 'scores' array by multiplying each score by 10
* field("scores").arrayTransform("score", multiply(variable("score"), 10));
* ```
*
* @param elementAlias The variable name to use for each element.
* @param transform The lambda expression used to transform the elements.
* @returns A new `Expression` representing the arrayTransform operation.
*/
arrayTransform(elementAlias, transform) {
return new FunctionExpression('array_transform', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(elementAlias),
transform,
]);
}
/**
* Creates an expression that applies a provided transformation to each element in an array, providing the element's index to the transformation expression.
*
* @example
* ```typescript
* // Transform the 'scores' array by adding the index to each score
* field("scores").arrayTransformWithIndex("score", "i", add(variable("score"), variable("i")));
* ```
*
* @param elementAlias The variable name to use for each element.
* @param indexAlias The variable name to use for the current index.
* @param transform The lambda expression used to transform the elements.
* @returns A new `Expression` representing the arrayTransformWithIndex operation.
*/
arrayTransformWithIndex(elementAlias, indexAlias, transform) {
return new FunctionExpression('array_transform', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(elementAlias),
(0, pipeline_util_1.valueToDefaultExpr)(indexAlias),
transform,
]);
}
/**
* Creates an expression that returns a slice of an array from `offset` with `length` elements.
*
* @example
* ```typescript
* // Get 5 elements from the 'items' array starting from index 2
* field("items").arraySlice(2, 5);
*
* // Get n number of elements from the 'items' array starting from index 2
* field("items").arraySlice(2, field("count"));
* ```
*
* @param offset The starting offset.
* @param length The optional length of the slice.
* @returns A new `Expression` representing the sliced array.
*/
arraySlice(offset, length) {
const args = [this, (0, pipeline_util_1.valueToDefaultExpr)(offset)];
if (length !== undefined) {
args.push((0, pipeline_util_1.valueToDefaultExpr)(length));
}
return new FunctionExpression('array_slice', args);
}
/**
* Creates an expression that reverses an array.
*
* @example
* ```typescript
* // Reverse the value of the 'myArray' field.
* field("myArray").arrayReverse();
* ```
*
* @returns A new `Expression` representing the reversed array.
*/
arrayReverse() {
return new FunctionExpression('array_reverse', [this]);
}
/**
* Creates an expression that calculates the length of an array.
*
* @example
* ```typescript
* // Get the number of items in the 'cart' array
* field("cart").arrayLength();
* ```
*
* @returns A new `Expression` representing the length of the array.
*/
arrayLength() {
return new FunctionExpression('array_length', [this]);
}
/**
* 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() {
return new FunctionExpression('array_first', [this]);
}
arrayFirstN(n) {
return new FunctionExpression('array_first_n', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(n),
]);
}
/**
* 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() {
return new FunctionExpression('array_last', [this]);
}
arrayLastN(n) {
return new FunctionExpression('array_last_n', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(n),
]);
}
/**
* 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() {
return new FunctionExpression('maximum', [this]);
}
arrayMaximumN(n) {
return new FunctionExpression('maximum_n', [this, (0, pipeline_util_1.valueToDefaultExpr)(n)]);
}
/**
* 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() {
return new FunctionExpression('minimum', [this]);
}
arrayMinimumN(n) {
return new FunctionExpression('minimum_n', [this, (0, pipeline_util_1.valueToDefaultExpr)(n)]);
}
arrayIndexOf(search) {
return new FunctionExpression('array_index_of', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(search),
(0, pipeline_util_1.valueToDefaultExpr)('first'),
]);
}
arrayLastIndexOf(search) {
return new FunctionExpression('array_index_of', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(search),
(0, pipeline_util_1.valueToDefaultExpr)('last'),
]);
}
arrayIndexOfAll(search) {
return new FunctionExpression('array_index_of_all', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(search),
]);
}
equalAny(others) {
const exprOthers = Array.isArray(others)
? new ListOfExprs(others.map(pipeline_util_1.valueToDefaultExpr))
: (0, util_1.cast)(others);
return new FunctionExpression('equal_any', [this, exprOthers]).asBoolean();
}
notEqualAny(others) {
const exprOthers = Array.isArray(others)
? new ListOfExprs(others.map(pipeline_util_1.valueToDefaultExpr))
: (0, util_1.cast)(others);
return new FunctionExpression('not_equal_any', [
this,
exprOthers,
]).asBoolean();
}
/**
* Creates an expression that checks if a field exists in the document.
*
* @example
* ```typescript
* // Check if the document has a field named "phoneNumber"
* field("phoneNumber").exists();
* ```
*
* @returns A new `Expression` representing the 'exists' check.
*/
exists() {
return new FunctionExpression('exists', [this]).asBoolean();
}
/**
* Creates an expression that calculates the character length of a string in UTF-8.
*
* @example
* ```typescript
* // Get the character length of the 'name' field in its UTF-8 form.
* field("name").charLength();
* ```
*
* @returns A new `Expression` representing the length of the string.
*/
charLength() {
return new FunctionExpression('char_length', [this]);
}
like(stringOrExpr) {
return new FunctionExpression('like', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(stringOrExpr),
]).asBoolean();
}
regexContains(stringOrExpr) {
return new FunctionExpression('regex_contains', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(stringOrExpr),
]).asBoolean();
}
regexFind(stringOrExpr) {
return new FunctionExpression('regex_find', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(stringOrExpr),
]);
}
regexFindAll(stringOrExpr) {
return new FunctionExpression('regex_find_all', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(stringOrExpr),
]);
}
regexMatch(stringOrExpr) {
return new FunctionExpression('regex_match', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(stringOrExpr),
]).asBoolean();
}
stringContains(stringOrExpr) {
return new FunctionExpression('string_contains', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(stringOrExpr),
]).asBoolean();
}
startsWith(stringOrExpr) {
return new FunctionExpression('starts_with', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(stringOrExpr),
]).asBoolean();
}
endsWith(stringOrExpr) {
return new FunctionExpression('ends_with', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(stringOrExpr),
]).asBoolean();
}
/**
* Creates an expression that converts a string to lowercase.
*
* @example
* ```typescript
* // Convert the 'name' field to lowercase
* field("name").toLower();
* ```
*
* @returns A new `Expression` representing the lowercase string.
*/
toLower() {
return new FunctionExpression('to_lower', [this]);
}
/**
* Creates an expression that converts a string to uppercase.
*
* @example
* ```typescript
* // Convert the 'title' field to uppercase
* field("title").toUpper();
* ```
*
* @returns A new `Expression` representing the uppercase string.
*/
toUpper() {
return new FunctionExpression('to_upper', [this]);
}
/**
* Creates an expression that removes leading and trailing characters from a string or byte array.
*
* @example
* ```typescript
* // Trim whitespace from the 'userInput' field
* field("userInput").trim();
*
* // Trim quotes from the 'userInput' field
* field("userInput").trim('"');
* ```
* @param valueToTrim Optional This parameter is treated as a set of characters or bytes that will be
* trimmed from the input. If not specified, then whitespace will be trimmed.
* @returns A new `Expr` representing the trimmed string or byte array.
*/
trim(valueToTrim) {
const args = [this];
if (valueToTrim) {
args.push((0, pipeline_util_1.valueToDefaultExpr)(valueToTrim));
}
return new FunctionExpression('trim', args);
}
/**
* Trims whitespace or a specified set of characters/bytes from the beginning of a string or byte array.
*
* @example
* ```typescript
* // Trim whitespace from the beginning of the 'userInput' field
* field("userInput").ltrim();
*
* // Trim quotes from the beginning of the 'userInput' field
* field("userInput").ltrim('"');
* ```
*
* @param valueToTrim Optional. A string or byte array containing the characters/bytes to trim.
* If not specified, whitespace will be trimmed.
* @returns A new `Expression` representing the trimmed string.
*/
ltrim(valueToTrim) {
const args = [this];
if (valueToTrim) {
args.push((0, pipeline_util_1.valueToDefaultExpr)(valueToTrim));
}
return new FunctionExpression('ltrim', args);
}
/**
* Trims whitespace or a specified set of characters/bytes from the end of a string or byte array.
*
* @example
* ```typescript
* // Trim whitespace from the end of the 'userInput' field
* field("userInput").rtrim();
*
* // Trim quotes from the end of the 'userInput' field
* field("userInput").rtrim('"');
* ```
*
* @param valueToTrim Optional. A string or byte array containing the characters/bytes to trim.
* If not specified, whitespace will be trimmed.
* @returns A new `Expression` representing the trimmed string or byte array.
*/
rtrim(valueToTrim) {
const args = [this];
if (valueToTrim) {
args.push((0, pipeline_util_1.valueToDefaultExpr)(valueToTrim));
}
return new FunctionExpression('rtrim', args);
}
/**
* Creates an expression that concatenates string expressions together.
*
* @example
* ```typescript
* // Combine the 'firstName', " ", and 'lastName' fields into a single string
* field("firstName").stringConcat(constant(" "), field("lastName"));
* ```
*
* @param secondString The additional expression or string literal to concatenate.
* @param otherStrings Optional additional expressions or string literals to concatenate.
* @returns A new `Expression` representing the concatenated string.
*/
stringConcat(secondString, ...otherStrings) {
const elements = [secondString, ...otherStrings];
const exprs = elements.map(pipeline_util_1.valueToDefaultExpr);
return new FunctionExpression('string_concat', [this, ...exprs]);
}
/**
* Creates an expression that finds the index of the first occurrence of a substring or byte sequence.
*
* @example
* ```typescript
* // Find the index of "foo" in the 'text' field
* field("text").stringIndexOf("foo");
* ```
*
* @param search The substring or byte sequence to search for.
* @returns A new `Expression` representing the index of the first occurrence.
*/
stringIndexOf(search) {
return new FunctionExpression('string_index_of', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(search),
]);
}
/**
* Creates an expression that repeats a string or byte array a specified number of times.
*
* @example
* ```typescript
* // Repeat the 'label' field 3 times
* field("label").stringRepeat(3);
* ```
*
* @param repetitions The number of times to repeat the string or byte array.
* @returns A new `Expression` representing the repeated string or byte array.
*/
stringRepeat(repetitions) {
return new FunctionExpression('string_repeat', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(repetitions),
]);
}
/**
* Creates an expression that replaces all occurrences of a substring or byte sequence with a replacement.
*
* @example
* ```typescript
* // Replace all occurrences of "foo" with "bar" in the 'text' field
* field("text").stringReplaceAll("foo", "bar");
* ```
*
* @param find The substring or byte sequence to search for.
* @param replacement The replacement string or byte sequence.
* @returns A new `Expression` representing the string or byte array with replacements.
*/
stringReplaceAll(find, replacement) {
return new FunctionExpression('string_replace_all', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(find),
(0, pipeline_util_1.valueToDefaultExpr)(replacement),
]);
}
/**
* Creates an expression that replaces the first occurrence of a substring or byte sequence with a replacement.
*
* @example
* ```typescript
* // Replace the first occurrence of "foo" with "bar" in the 'text' field
* field("text").stringReplaceOne("foo", "bar");
* ```
*
* @param find The substring or byte sequence to search for.
* @param replacement The replacement string or byte sequence.
* @returns A new `Expression` representing the string or byte array with the replacement.
*/
stringReplaceOne(find, replacement) {
return new FunctionExpression('string_replace_one', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(find),
(0, pipeline_util_1.valueToDefaultExpr)(replacement),
]);
}
/**
* Creates an expression that concatenates expression results together.
*
* @example
* ```typescript
* // Combine the 'firstName', ' ', and 'lastName' fields into a single value.
* field("firstName").concat(constant(" "), field("lastName"));
* ```
*
* @param second The additional expression or literal to concatenate.
* @param others Optional additional expressions or literals to concatenate.
* @returns A new `Expr` representing the concatenated value.
*/
concat(second, ...others) {
const elements = [second, ...others];
const exprs = elements.map(pipeline_util_1.valueToDefaultExpr);
return new FunctionExpression('concat', [this, ...exprs]);
}
/**
* Creates an expression that reverses this string or bytes expression.
*
* @example
* ```typescript
* // Reverse the value of the 'myString' field.
* field("myString").reverse();
* ```
*
* @returns A new `Expression` representing the reversed string or bytes.
*/
reverse() {
return new FunctionExpression('reverse', [this]);
}
/**
* Creates an expression that calculates the length of this string expression in bytes.
*
* @example
* ```typescript
* // Calculate the length of the 'myString' field in bytes.
* field("myString").byteLength();
* ```
*
* @returns A new `Expression` representing the length of the string in bytes.
*/
byteLength() {
return new FunctionExpression('byte_length', [this]);
}
/**
* Creates an expression that computes the ceiling of a numeric value.
*
* @example
* ```typescript
* // Compute the ceiling of the 'price' field.
* field("price").ceil();
* ```
*
* @returns A new `Expression` representing the ceiling of the numeric value.
*/
ceil() {
return new FunctionExpression('ceil', [this]);
}
/**
* Creates an expression that computes the floor of a numeric value.
*
* @example
* ```typescript
* // Compute the floor of the 'price' field.
* field("price").floor();
* ```
*
* @returns A new `Expression` representing the floor of the numeric value.
*/
floor() {
return new FunctionExpression('floor', [this]);
}
/**
* Creates an expression that computes the absolute value of a numeric value.
*
* @example
* ```typescript
* // Compute the absolute value of the 'price' field.
* field("price").abs();
* ```
*
* @returns A new `Expr` representing the absolute value of the numeric value.
*/
abs() {
return new FunctionExpression('abs', [this]);
}
/**
* Creates an expression that computes e to the power of this expression.
*
* @example
* ```typescript
* // Compute e to the power of the 'value' field.
* field("value").exp();
* ```
*
* @returns A new `Expression` representing the exp of the numeric value.
*/
exp() {
return new FunctionExpression('exp', [this]);
}
/**
* Accesses a value from a map (object) field using the provided key.
*
* @example
* ```typescript
* // Get the 'city' value from the 'address' map field
* field("address").mapGet("city");
* ```
*
* @param subfield The key to access in the map.
* @returns A new `Expression` representing the value associated with the given key in the map.
*/
mapGet(subfield) {
return new FunctionExpression('map_get', [this, constant(subfield)]);
}
/**
* Creates an expression that returns a new map with the specified entries added or updated.
*
* @remarks
* Note that `mapSet` only performs shallow updates to the map. Setting a value to `null`
* will retain the key with a `null` value. To remove a key entirely, use `mapRemove`.
*
* @example
* ```typescript
* // Set the 'city' to "San Francisco" in the 'address' map
* field("address").mapSet("city", "San Francisco");
* ```
*
* @param key The key to set. Must be a string or a constant string expression.
* @param value The value to set.
* @param moreKeyValues Additional key-value pairs to set.
* @returns A new `Expression` representing the map with the entries set.
*/
mapSet(key, value, ...moreKeyValues) {
const args = [
this,
(0, pipeline_util_1.valueToDefaultExpr)(key),
(0, pipeline_util_1.valueToDefaultExpr)(value),
...moreKeyValues.map(pipeline_util_1.valueToDefaultExpr),
];
return new FunctionExpression('map_set', args);
}
/**
* Creates an expression that returns the keys of a map.
*
* @remarks
* While the backend generally preserves insertion order, relying on the
* order of the output array is not guaranteed and should be avoided.
*
* @example
* ```typescript
* // Get the keys of the 'address' map
* field("address").mapKeys();
* ```
*
* @returns A new `Expression` representing the keys of the map.
*/
mapKeys() {
return new FunctionExpression('map_keys', [this]);
}
/**
* Creates an expression that returns the values of a map.
*
* @remarks
* While the backend generally preserves insertion order, relying on the
* order of the output array is not guaranteed and should be avoided.
*
* @example
* ```typescript
* // Get the values of the 'address' map
* field("address").mapValues();
* ```
*
* @returns A new `Expression` representing the values of the map.
*/
mapValues() {
return new FunctionExpression('map_values', [this]);
}
/**
* Creates an expression that returns the entries of a map as an array of maps,
* where each map contains a `"k"` property for the key and a `"v"` property for the value.
* For example: `[{ k: "key1", v: "value1" }, ...]`.
*
* @remarks
* While the backend generally preserves insertion order, relying on the
* order of the output array is not guaranteed and should be avoided.
*
* @example
* ```typescript
* // Get the entries of the 'address' map
* field("address").mapEntries();
* ```
*
* @returns A new `Expression` representing the entries of the map.
*/
mapEntries() {
return new FunctionExpression('map_entries', [this]);
}
/**
* Creates an aggregation that counts the number of stage inputs with valid evaluations of the
* expression or field.
*
* @example
* ```typescript
* // Count the total number of products
* field("productId").count().as("totalProducts");
* ```
*
* @returns A new `AggregateFunction` representing the 'count' aggregation.
*/
count() {
return new AggregateFunction('count', [this]);
}
/**
* Creates an aggregation that calculates the sum of a numeric field across multiple stage inputs.
*
* @example
* ```typescript
* // Calculate the total revenue from a set of orders
* field("orderAmount").sum().as("totalRevenue");
* ```
*
* @returns A new `AggregateFunction` representing the 'sum' aggregation.
*/
sum() {
return new AggregateFunction('sum', [this]);
}
/**
* Creates an aggregation that calculates the average (mean) of a numeric field across multiple
* stage inputs.
*
* @example
* ```typescript
* // Calculate the average age of users
* field("age").average().as("averageAge");
* ```
*
* @returns A new `AggregateFunction` representing the 'average' aggregation.
*/
average() {
return new AggregateFunction('average', [this]);
}
/**
* Creates an aggregation that finds the minimum value of a field across multiple stage inputs.
*
* @example
* ```typescript
* // Find the lowest price of all products
* field("price").minimum().as("lowestPrice");
* ```
*
* @returns A new `AggregateFunction` representing the 'min' aggregation.
*/
minimum() {
return new AggregateFunction('minimum', [this]);
}
/**
* Creates an aggregation that finds the maximum value of a field across multiple stage inputs.
*
* @example
* ```typescript
* // Find the highest score in a leaderboard
* field("score").maximum().as("highestScore");
* ```
*
* @returns A new `AggregateFunction` representing the 'max' aggregation.
*/
maximum() {
return new AggregateFunction('maximum', [this]);
}
/**
* Creates an aggregation that finds the first value of an expression across multiple stage inputs.
*
* @example
* ```typescript
* // Find the first value of the 'rating' field
* field("rating").first().as("firstRating");
* ```
*
* @returns A new `AggregateFunction` representing the 'first' aggregation.
*/
first() {
return new AggregateFunction('first', [this]);
}
/**
* Creates an aggregation that finds the last value of an expression across multiple stage inputs.
*
* @example
* ```typescript
* // Find the last value of the 'rating' field
* field("rating").last().as("lastRating");
* ```
*
* @returns A new `AggregateFunction` representing the 'last' aggregation.
*/
last() {
return new AggregateFunction('last', [this]);
}
/**
* Creates an aggregation that collects all values of an expression across multiple stage inputs
* into an array.
*
* @remarks
* If the expression resolves to an absent value, it is converted to `null`.
* The order of elements in the output array is not stable and shouldn't be relied upon.
*
* @example
* ```typescript
* // Collect all tags from books into an array
* field("tags").arrayAgg().as("allTags");
* ```
*
* @returns A new `AggregateFunction` representing the 'array_agg' aggregation.
*/
arrayAgg() {
return new AggregateFunction('array_agg', [this]);
}
/**
* Creates an aggregation that collects all distinct values of an expression across multiple stage
* inputs into an array.
*
* @remarks
* If the expression resolves to an absent value, it is converted to `null`.
* The order of elements in the output array is not stable and shouldn't be relied upon.
*
* @example
* ```typescript
* // Collect all distinct tags from books into an array
* field("tags").arrayAggDistinct().as("allDistinctTags");
* ```
*
* @returns A new `AggregateFunction` representing the 'array_agg_distinct' aggregation.
*/
arrayAggDistinct() {
return new AggregateFunction('array_agg_distinct', [this]);
}
/**
* Creates an aggregation that counts the number of distinct values of the expression or field.
*
* @example
* ```typescript
* // Count the distinct number of products
* field("productId").countDistinct().as("distinctProducts");
* ```
*
* @returns A new `AggregateFunction` representing the 'count_distinct' aggregation.
*/
countDistinct() {
return new AggregateFunction('count_distinct', [this]);
}
/**
* Creates an expression that returns the larger value between this expression and another expression, based on Firestore's value type ordering.
*
* @example
* ```typescript
* // Returns the larger value between the 'timestamp' field and the current timestamp.
* field("timestamp").logicalMaximum(Function.currentTimestamp());
* ```
*
* @param second The second expression or literal to compare with.
* @param others Optional additional expressions or literals to compare with.
* @returns A new `Expression` representing the logical max operation.
*/
logicalMaximum(second, ...others) {
const values = [second, ...others];
return new FunctionExpression('maximum', [
this,
...values.map(pipeline_util_1.valueToDefaultExpr),
]);
}
/**
* Creates an expression that returns the smaller value between this expression and another expression, based on Firestore's value type ordering.
*
* @example
* ```typescript
* // Returns the smaller value between the 'timestamp' field and the current timestamp.
* field("timestamp").logicalMinimum(Function.currentTimestamp());
* ```
*
* @param second The second expression or literal to compare with.
* @param others Optional additional expressions or literals to compare with.
* @returns A new `Expression` representing the logical min operation.
*/
logicalMinimum(second, ...others) {
const values = [second, ...others];
return new FunctionExpression('minimum', [
this,
...values.map(pipeline_util_1.valueToDefaultExpr),
]);
}
/**
* Creates an expression that calculates the length (number of dimensions) of this Firestore Vector expression.
*
* @example
* ```typescript
* // Get the vector length (dimension) of the field 'embedding'.
* field("embedding").vectorLength();
* ```
*
* @returns A new `Expression` representing the length of the vector.
*/
vectorLength() {
return new FunctionExpression('vector_length', [this]);
}
cosineDistance(other) {
return new FunctionExpression('cosine_distance', [
this,
(0, pipeline_util_1.vectorToExpr)(other),
]);
}
dotProduct(other) {
return new FunctionExpression('dot_product', [this, (0, pipeline_util_1.vectorToExpr)(other)]);
}
euclideanDistance(other) {
return new FunctionExpression('euclidean_distance', [
this,
(0, pipeline_util_1.vectorToExpr)(other),
]);
}
/**
* Creates an expression that interprets this expression as the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC)
* and returns a timestamp.
*
* @example
* ```typescript
* // Interpret the 'microseconds' field as microseconds since epoch.
* field("microseconds").unixMicrosToTimestamp();
* ```
*
* @returns A new `Expression` representing the timestamp.
*/
unixMicrosToTimestamp() {
return new FunctionExpression('unix_micros_to_timestamp', [this]);
}
/**
* Creates an expression that converts this timestamp expression to the number of microseconds since the Unix epoch (1970-01-01 00:00:00 UTC).
*
* @example
* ```typescript
* // Convert the 'timestamp' field to microseconds since epoch.
* field("timestamp").timestampToUnixMicros();
* ```
*
* @returns A new `Expression` representing the number of microseconds since epoch.
*/
timestampToUnixMicros() {
return new FunctionExpression('timestamp_to_unix_micros', [this]);
}
/**
* Creates an expression that interprets this expression as the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC)
* and returns a timestamp.
*
* @example
* ```typescript
* // Interpret the 'milliseconds' field as milliseconds since epoch.
* field("milliseconds").unixMillisToTimestamp();
* ```
*
* @returns A new `Expression` representing the timestamp.
*/
unixMillisToTimestamp() {
return new FunctionExpression('unix_millis_to_timestamp', [this]);
}
/**
* Creates an expression that converts this timestamp expression to the number of milliseconds since the Unix epoch (1970-01-01 00:00:00 UTC).
*
* @example
* ```typescript
* // Convert the 'timestamp' field to milliseconds since epoch.
* field("timestamp").timestampToUnixMillis();
* ```
*
* @returns A new `Expression` representing the number of milliseconds since epoch.
*/
timestampToUnixMillis() {
return new FunctionExpression('timestamp_to_unix_millis', [this]);
}
/**
* Creates an expression that interprets this expression as the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC)
* and returns a timestamp.
*
* @example
* ```typescript
* // Interpret the 'seconds' field as seconds since epoch.
* field("seconds").unixSecondsToTimestamp();
* ```
*
* @returns A new `Expression` representing the timestamp.
*/
unixSecondsToTimestamp() {
return new FunctionExpression('unix_seconds_to_timestamp', [this]);
}
/**
* Creates an expression that converts this timestamp expression to the number of seconds since the Unix epoch (1970-01-01 00:00:00 UTC).
*
* @example
* ```typescript
* // Convert the 'timestamp' field to seconds since epoch.
* field("timestamp").timestampToUnixSeconds();
* ```
*
* @returns A new `Expression` representing the number of seconds since epoch.
*/
timestampToUnixSeconds() {
return new FunctionExpression('timestamp_to_unix_seconds', [this]);
}
timestampAdd(unit, amount) {
return new FunctionExpression('timestamp_add', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(unit),
(0, pipeline_util_1.valueToDefaultExpr)(amount),
]);
}
timestampSubtract(unit, amount) {
return new FunctionExpression('timestamp_subtract', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(unit),
(0, pipeline_util_1.valueToDefaultExpr)(amount),
]);
}
timestampDiff(start, unit) {
return new FunctionExpression('timestamp_diff', [
this,
(0, pipeline_util_1.fieldOrExpression)(start),
(0, pipeline_util_1.valueToDefaultExpr)(unit),
]);
}
timestampExtract(part, timezone) {
const args = [this, (0, pipeline_util_1.valueToDefaultExpr)(part)];
if (timezone) {
args.push((0, pipeline_util_1.valueToDefaultExpr)(timezone));
}
return new FunctionExpression('timestamp_extract', args);
}
/**
* Creates an expression that returns the document ID from a path.
*
* @example
* ```typescript
* // Get the document ID from a path.
* field("__path__").documentId();
* ```
*
* @returns A new `Expression` representing the documentId operation.
*/
documentId() {
return new FunctionExpression('document_id', [this]);
}
/**
*
* Creates an expression that returns the parent document of a document reference.
*
* @example
* ```typescript
* // Get the parent document of a document reference.
* field("__path__").parent();
* ```
*
* @returns A new `Expression` representing the parent operation.
*/
parent() {
return new FunctionExpression('parent', [this]);
}
substring(position, length) {
const positionExpr = (0, pipeline_util_1.valueToDefaultExpr)(position);
if (length === undefined) {
return new FunctionExpression('substring', [this, positionExpr]);
}
else {
return new FunctionExpression('substring', [
this,
positionExpr,
(0, pipeline_util_1.valueToDefaultExpr)(length),
]);
}
}
arrayGet(index) {
return new FunctionExpression('array_get', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(index),
]);
}
/**
* Creates an expression that checks if a given expression produces an error.
*
* @example
* ```typescript
* // Check if the result of a calculation is an error
* field("title").arrayContains(1).isError();
* ```
*
* @returns A new `BooleanExpression` representing the 'isError' check.
*/
isError() {
return new FunctionExpression('is_error', [this]).asBoolean();
}
ifError(catchValue) {
return new FunctionExpression('if_error', [
this,
(0, pipeline_util_1.valueToDefaultExpr)(catchValue),
]);
}
/**
* Creates an expression that returns `true` if the result of this expression
*