UNPKG

@google-cloud/firestore

Version:
1,437 lines 120 kB
"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 *