UNPKG

@configurator/ravendb

Version:
1,116 lines 71.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AbstractDocumentQuery = void 0; const QueryOperation_1 = require("./Operations/QueryOperation"); const GroupByCountToken_1 = require("./Tokens/GroupByCountToken"); const GroupByToken_1 = require("./Tokens/GroupByToken"); const HighlightingToken_1 = require("./Tokens/HighlightingToken"); const FieldsToFetchToken_1 = require("./Tokens/FieldsToFetchToken"); const FromToken_1 = require("./Tokens/FromToken"); const DistinctToken_1 = require("./Tokens/DistinctToken"); const QueryStatistics_1 = require("./QueryStatistics"); const Exceptions_1 = require("../../Exceptions"); const IndexQuery_1 = require("../Queries/IndexQuery"); const GroupBy_1 = require("../Queries/GroupBy"); const GroupByKeyToken_1 = require("../Session/Tokens/GroupByKeyToken"); const GroupBySumToken_1 = require("../Session/Tokens/GroupBySumToken"); const ExplanationToken_1 = require("../Session/Tokens/ExplanationToken"); const TimingsToken_1 = require("../Session/Tokens/TimingsToken"); const TrueToken_1 = require("../Session/Tokens/TrueToken"); const WhereToken_1 = require("../Session/Tokens/WhereToken"); const QueryFieldUtil_1 = require("../Queries/QueryFieldUtil"); const CloseSubclauseToken_1 = require("./Tokens/CloseSubclauseToken"); const OpenSubclauseToken_1 = require("./Tokens/OpenSubclauseToken"); const NegateToken_1 = require("./Tokens/NegateToken"); const WhereParams_1 = require("./WhereParams"); const TypeUtil_1 = require("../../Utility/TypeUtil"); const DateUtil_1 = require("../../Utility/DateUtil"); const MethodCall_1 = require("./MethodCall"); const QueryOperatorToken_1 = require("./Tokens/QueryOperatorToken"); const OrderByToken_1 = require("./Tokens/OrderByToken"); const FacetToken_1 = require("./Tokens/FacetToken"); const CounterIncludesToken_1 = require("./Tokens/CounterIncludesToken"); const events_1 = require("events"); const StringUtil_1 = require("../../Utility/StringUtil"); const IntersectMarkerToken_1 = require("./Tokens/IntersectMarkerToken"); const DocumentConventions_1 = require("../Conventions/DocumentConventions"); const Constants_1 = require("../../Constants"); const DocumentQueryHelper_1 = require("./DocumentQueryHelper"); const ShapeToken_1 = require("./Tokens/ShapeToken"); const SessionEvents_1 = require("./SessionEvents"); const CmpXchg_1 = require("./CmpXchg"); const DocumentQueryCustomization_1 = require("./DocumentQueryCustomization"); const MoreLikeThisScope_1 = require("../Queries/MoreLikeThis/MoreLikeThisScope"); const MoreLikeThisToken_1 = require("./Tokens/MoreLikeThisToken"); const LazyQueryOperation_1 = require("../Session/Operations/Lazy/LazyQueryOperation"); const SuggestToken_1 = require("./Tokens/SuggestToken"); const SuggestionWithTerm_1 = require("../Queries/Suggestions/SuggestionWithTerm"); const SuggestionWithTerms_1 = require("../Queries/Suggestions/SuggestionWithTerms"); const QueryData_1 = require("../Queries/QueryData"); const QueryTimings_1 = require("../Queries/Timings/QueryTimings"); const Explanations_1 = require("../Queries/Explanation/Explanations"); const HighlightingOptions_1 = require("../Queries/Highlighting/HighlightingOptions"); const QueryHighlightings_1 = require("../Queries/Highlighting/QueryHighlightings"); const os = require("os"); const GraphQueryToken_1 = require("./Tokens/GraphQueryToken"); const IncludesUtil_1 = require("./IncludesUtil"); const TimeSeriesIncludesToken_1 = require("./Tokens/TimeSeriesIncludesToken"); const CompareExchangeValueIncludesToken_1 = require("./Tokens/CompareExchangeValueIncludesToken"); const TimeSeriesQueryBuilder_1 = require("../Queries/TimeSeries/TimeSeriesQueryBuilder"); const StringBuilder_1 = require("../../Utility/StringBuilder"); const RevisionIncludesToken_1 = require("./Tokens/RevisionIncludesToken"); class AbstractDocumentQuery extends events_1.EventEmitter { get indexName() { return this._indexName; } get collectionName() { return this._collectionName; } isFilterActive() { return this._filterModeStack.length && this._filterModeStack[0]; } get isDistinct() { return this._selectTokens && this._selectTokens.length && this._selectTokens[0] instanceof DistinctToken_1.DistinctToken; } get theWaitForNonStaleResults() { return this._theWaitForNonStaleResults; } get timeout() { return this._timeout; } get queryParameters() { return this._queryParameters; } get selectTokens() { return this._selectTokens; } get isProjectInto() { return this._isProjectInto; } set isProjectInto(value) { this._isProjectInto = value; } get conventions() { return this._conventions; } get session() { return this._theSession; } isDynamicMapReduce() { return this._groupByTokens && !!this._groupByTokens.length; } _getDefaultTimeout() { return this._conventions.waitForNonStaleResultsTimeout; } constructor(clazz, session, indexName, collectionName, isGroupBy, declareTokens, loadTokens, fromAlias = null, isProjectInto = false) { super(); this._aliasToGroupByFieldName = {}; this._defaultOperator = "AND"; this._rootTypes = new Set(); this._filterModeStack = []; this._queryParameters = {}; this._selectTokens = []; this._whereTokens = []; this._groupByTokens = []; this._orderByTokens = []; this._withTokens = []; this._filterTokens = []; this._documentIncludes = new Set(); this._statsCallback = TypeUtil_1.TypeUtil.NOOP; this._queryStats = new QueryStatistics_1.QueryStatistics(); this._parameterPrefix = "p"; this._highlightingTokens = []; this._queryHighlightings = new QueryHighlightings_1.QueryHighlightings(); this._clazz = clazz; this._rootTypes.add(clazz); this._isGroupBy = isGroupBy; this._indexName = indexName; this._collectionName = collectionName; this._fromToken = FromToken_1.FromToken.create(indexName, collectionName, fromAlias); this._declareTokens = declareTokens; this._loadTokens = loadTokens; this._theSession = session; this.on("afterQueryExecuted", (result) => { this._updateStatsAndHighlightingsAndExplanations(result); }); this._conventions = !session ? new DocumentConventions_1.DocumentConventions() : session.conventions; this._isProjectInto = isProjectInto || false; } _assertMethodIsCurrentlySupported(methodName) { if (!this.isFilterActive()) { return; } (0, Exceptions_1.throwError)("InvalidQueryException", methodName + " is currently unsupported for 'filter'. If you want to use" + methodName + " in where method you have to put it before 'filter'"); } _getCurrentWhereTokens() { if (this.isFilterActive()) { return this._filterTokens; } if (!this._isInMoreLikeThis) { return this._whereTokens; } if (!this._whereTokens || !this._whereTokens.length) { (0, Exceptions_1.throwError)("InvalidOperationException", "Cannot get MoreLikeThisToken because there are no where token specified."); } const lastToken = this._whereTokens[this._whereTokens.length - 1]; if (lastToken instanceof MoreLikeThisToken_1.MoreLikeThisToken) { return lastToken.whereTokens; } else { (0, Exceptions_1.throwError)("InvalidOperationException", "Last token is not MoreLikeThisToken"); } } _ensureValidFieldName(fieldName, isNestedPath) { if (!this._theSession || !this._theSession.conventions || isNestedPath || this._isGroupBy) { return QueryFieldUtil_1.QueryFieldUtil.escapeIfNecessary(fieldName, isNestedPath); } for (const rootType of this._rootTypes) { const identityProperty = this._theSession.conventions.getIdentityProperty(rootType); if (identityProperty && identityProperty === fieldName) { return Constants_1.CONSTANTS.Documents.Indexing.Fields.DOCUMENT_ID_FIELD_NAME; } } return QueryFieldUtil_1.QueryFieldUtil.escapeIfNecessary(fieldName); } _appendOperatorIfNeeded(tokens) { this._assertNoRawQuery(); if (!tokens || !tokens.length) { return; } const lastToken = tokens[tokens.length - 1]; if (!(lastToken instanceof WhereToken_1.WhereToken) && !(lastToken instanceof CloseSubclauseToken_1.CloseSubclauseToken)) { return; } let lastWhere = null; for (let i = tokens.length - 1; i >= 0; i--) { if (tokens[i] instanceof WhereToken_1.WhereToken) { lastWhere = tokens[i]; break; } } let token = this._defaultOperator === "AND" ? QueryOperatorToken_1.QueryOperatorToken.AND : QueryOperatorToken_1.QueryOperatorToken.OR; if (lastWhere && lastWhere.options.searchOperator) { token = QueryOperatorToken_1.QueryOperatorToken.OR; } tokens.push(token); } _transformCollection(fieldName, values) { const result = []; for (const value of values) { if (Array.isArray(value)) { result.push(...this._transformCollection(fieldName, value)); } else { const nestedWhereParams = new WhereParams_1.WhereParams(); nestedWhereParams.allowWildcards = true; nestedWhereParams.fieldName = fieldName; nestedWhereParams.value = value; result.push(this._transformValue(nestedWhereParams)); } } return result; } _negateIfNeeded(tokens, fieldName) { if (!this._negate) { return; } this._negate = false; if (!tokens || !tokens.length || tokens[tokens.length - 1] instanceof OpenSubclauseToken_1.OpenSubclauseToken) { if (fieldName) { this._whereExists(fieldName); } else { this._whereTrue(); } this._andAlso(); } tokens.push(NegateToken_1.NegateToken.INSTANCE); } _usingDefaultOperator(operator) { if (this._getCurrentWhereTokens().length > 0) { (0, Exceptions_1.throwError)("InvalidOperationException", "Default operator can only be set before any where clause is added."); } this._defaultOperator = operator; } _waitForNonStaleResults(waitTimeout) { if (this._theWaitForNonStaleResults) { if (!this._timeout || waitTimeout && this._timeout < waitTimeout) { this._timeout = waitTimeout; } return; } this._theWaitForNonStaleResults = true; this._timeout = waitTimeout || this._getDefaultTimeout(); } _getLazyQueryOperation() { if (!this._queryOperation) { this._queryOperation = this.initializeQueryOperation(); } const clazz = this._conventions.getJsTypeByDocumentType(this._clazz); return new LazyQueryOperation_1.LazyQueryOperation(this._theSession, this._queryOperation, this, clazz); } initializeQueryOperation() { const beforeQueryEventArgs = new SessionEvents_1.SessionBeforeQueryEventArgs(this._theSession, new DocumentQueryCustomization_1.DocumentQueryCustomization(this)); this._theSession.emit("beforeQuery", beforeQueryEventArgs); const indexQuery = this.getIndexQuery(); return new QueryOperation_1.QueryOperation(this._theSession, this._indexName, indexQuery, this.fieldsToFetchToken, this._disableEntitiesTracking, false, false, this._isProjectInto); } _transformValue(whereParams, forRange = false) { if (TypeUtil_1.TypeUtil.isNullOrUndefined(whereParams.value)) { return null; } if ("" === whereParams.value) { return ""; } let objectValue = null; if (this._conventions.tryConvertValueToObjectForQuery(whereParams.fieldName, whereParams.value, forRange, s => objectValue = s)) { return objectValue; } const value = whereParams.value; return this._stringifyParameter(value); } _stringifyParameter(value) { if (TypeUtil_1.TypeUtil.isDate(value)) { return DateUtil_1.DateUtil.utc.stringify(value); } if (TypeUtil_1.TypeUtil.isString(value)) { return value; } if (TypeUtil_1.TypeUtil.isNumber(value)) { return value; } if (value === false || value === true) { return value; } return value || null; } _addQueryParameter(value) { const parameterName = this.parameterPrefix + Object.keys(this._queryParameters).length; this._queryParameters[parameterName] = this._stringifyParameter(value); return parameterName; } static _getSourceAliasIfExists(documentType, queryData, fields, sourceAlias) { sourceAlias(null); if (fields.length !== 1 || !fields[0]) { return; } const indexOf = fields[0].indexOf("."); if (indexOf === -1) { return; } const possibleAlias = fields[0].substring(0, indexOf); if (queryData.fromAlias && queryData.fromAlias === possibleAlias) { sourceAlias(possibleAlias); return; } if (!queryData.loadTokens || queryData.loadTokens.length === 0) { return; } if (!queryData.loadTokens.find(x => x.alias === possibleAlias)) { return; } sourceAlias(possibleAlias); } _createTimeSeriesQueryData(timeSeriesQuery) { const builder = new TimeSeriesQueryBuilder_1.TimeSeriesQueryBuilder(); timeSeriesQuery(builder); const fields = [Constants_1.TIME_SERIES.SELECT_FIELD_NAME + "(" + builder.queryText + ")"]; const projections = [Constants_1.TIME_SERIES.QUERY_FUNCTION]; return new QueryData_1.QueryData(fields, projections); } _addFilterLimit(filterLimit) { if (filterLimit <= 0) { (0, Exceptions_1.throwError)("InvalidOperationException", "filterLimit need to be positive and bigger than 0."); } if (filterLimit !== Number.MAX_SAFE_INTEGER) { this._filterLimit = filterLimit; } } _getCurrentOrderByTokens() { return this._orderByTokens; } _getCurrentFilterTokens() { return this._filterTokens; } _updateFieldsToFetchToken(fieldsToFetch) { this.fieldsToFetchToken = fieldsToFetch; if (this._selectTokens && !this._selectTokens.length) { this._selectTokens.push(fieldsToFetch); } else { const fetchToken = [...this._selectTokens] .filter(x => x instanceof FieldsToFetchToken_1.FieldsToFetchToken)[0]; if (fetchToken) { const idx = this._selectTokens.indexOf(fetchToken); this._selectTokens[idx] = fieldsToFetch; } else { this._selectTokens.push(fieldsToFetch); } } } getIndexQuery() { let serverVersion = null; if (this._theSession && this._theSession.requestExecutor) { serverVersion = this._theSession.requestExecutor.lastServerVersion; } const compatibilityMode = serverVersion && serverVersion.localeCompare("4.2") < 0; const query = this.toString(compatibilityMode); const indexQuery = this._generateIndexQuery(query); this.emit("beforeQueryExecuted", indexQuery); return indexQuery; } getProjectionFields() { return this.fieldsToFetchToken && this.fieldsToFetchToken.projections ? [...this.fieldsToFetchToken.projections] : []; } _randomOrdering(seed) { this._assertNoRawQuery(); this._noCaching(); if (!seed) { this._orderByTokens.push(OrderByToken_1.OrderByToken.random); return; } this._orderByTokens.push(OrderByToken_1.OrderByToken.createRandom(seed)); } _projection(projectionBehavior) { this.projectionBehavior = projectionBehavior; } addGroupByAlias(fieldName, projectedName) { this._aliasToGroupByFieldName[projectedName] = fieldName; } _assertNoRawQuery() { if (this._queryRaw) { (0, Exceptions_1.throwError)("InvalidOperationException", "RawQuery was called, cannot modify this query by calling on " + "operations that would modify the query (such as Where, Select, OrderBy, GroupBy, etc)"); } } _graphQuery(query) { this._graphRawQuery = new GraphQueryToken_1.GraphQueryToken(query); } addParameter(name, value) { name = name.replace(/^\$/, ""); if (Object.keys(this._queryParameters).indexOf(name) !== -1) { (0, Exceptions_1.throwError)("InvalidOperationException", "The parameter " + name + " was already added"); } this._queryParameters[name] = value; } _groupBy(fieldOrFieldName, ...fieldsOrFieldNames) { if (typeof (fieldOrFieldName) === "string") { const mapping = fieldsOrFieldNames.map(x => GroupBy_1.GroupBy.field(x)); this._groupBy(GroupBy_1.GroupBy.field(fieldOrFieldName), ...mapping); return; } if (!this._fromToken.isDynamic) { (0, Exceptions_1.throwError)("InvalidOperationException", "groupBy only works with dynamic queries"); } this._assertNoRawQuery(); this._isGroupBy = true; const fieldName = this._ensureValidFieldName(fieldOrFieldName.field, false); this._groupByTokens.push(GroupByToken_1.GroupByToken.create(fieldName, fieldOrFieldName.method)); if (!fieldsOrFieldNames || !fieldsOrFieldNames.length) { return; } for (const item of fieldsOrFieldNames) { fieldOrFieldName = this._ensureValidFieldName(item.field, false); this._groupByTokens.push(GroupByToken_1.GroupByToken.create(fieldOrFieldName, item.method)); } } _groupByKey(fieldName, projectedName = null) { this._assertNoRawQuery(); this._isGroupBy = true; if (projectedName && this._aliasToGroupByFieldName[projectedName]) { const aliasedFieldName = this._aliasToGroupByFieldName[projectedName]; if (!fieldName || fieldName.toLocaleLowerCase() === (projectedName || "").toLocaleLowerCase()) { fieldName = aliasedFieldName; } } else if (fieldName && Object.keys(this._aliasToGroupByFieldName) .reduce((result, next) => result || next === fieldName, false)) { fieldName = this._aliasToGroupByFieldName[fieldName]; } this._selectTokens.push(GroupByKeyToken_1.GroupByKeyToken.create(fieldName, projectedName)); } _groupBySum(fieldName, projectedName = null) { this._assertNoRawQuery(); this._isGroupBy = true; fieldName = this._ensureValidFieldName(fieldName, false); this._selectTokens.push(GroupBySumToken_1.GroupBySumToken.create(fieldName, projectedName)); } _groupByCount(projectedName = null) { this._assertNoRawQuery(); this._isGroupBy = true; this._selectTokens.push(GroupByCountToken_1.GroupByCountToken.create(projectedName)); } _whereTrue() { const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, null); tokens.push(TrueToken_1.TrueToken.INSTANCE); } _moreLikeThis() { this._appendOperatorIfNeeded(this._whereTokens); const token = new MoreLikeThisToken_1.MoreLikeThisToken(); this._whereTokens.push(token); this._isInMoreLikeThis = true; return new MoreLikeThisScope_1.MoreLikeThisScope(token, v => this._addQueryParameter(v), () => this._isInMoreLikeThis = false); } _include(pathOrIncludes) { if (!pathOrIncludes) { return; } if (TypeUtil_1.TypeUtil.isString(pathOrIncludes)) { this._documentIncludes.add(pathOrIncludes); return; } const { documentsToInclude } = pathOrIncludes; if (documentsToInclude) { for (const doc of documentsToInclude) { this._documentIncludes.add(doc); } } this._includeCounters(pathOrIncludes.alias, pathOrIncludes.countersToIncludeBySourcePath); if (pathOrIncludes.timeSeriesToIncludeBySourceAlias) { this._includeTimeSeries(pathOrIncludes.alias, pathOrIncludes.timeSeriesToIncludeBySourceAlias); } if (pathOrIncludes.revisionsToIncludeByDateTime) { this._includeRevisionsByDate(pathOrIncludes.revisionsToIncludeByDateTime); } if (pathOrIncludes.revisionsToIncludeByChangeVector) { this._includeRevisionsByChangeVector(pathOrIncludes.revisionsToIncludeByChangeVector); } if (pathOrIncludes.compareExchangeValuesToInclude) { this._compareExchangeValueIncludesTokens = []; for (const compareExchangeValue of pathOrIncludes.compareExchangeValuesToInclude) { this._compareExchangeValueIncludesTokens.push(CompareExchangeValueIncludesToken_1.CompareExchangeValueIncludesToken.create(compareExchangeValue)); } } } _take(count) { this._pageSize = count; } _skip(count) { this._start = count; } _whereLucene(fieldName, whereClause, exact) { fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const options = exact ? new WhereToken_1.WhereOptions({ exact }) : null; const whereToken = WhereToken_1.WhereToken.create("Lucene", fieldName, this._addQueryParameter(whereClause), options); tokens.push(whereToken); } _openSubclause() { this._currentClauseDepth++; const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, null); tokens.push(OpenSubclauseToken_1.OpenSubclauseToken.create()); } _closeSubclause() { this._currentClauseDepth--; const tokens = this._getCurrentWhereTokens(); tokens.push(CloseSubclauseToken_1.CloseSubclauseToken.create()); } _whereEquals(fieldNameOrWhereParams, value, exact = false) { if (!TypeUtil_1.TypeUtil.isObject(fieldNameOrWhereParams)) { const params = new WhereParams_1.WhereParams(); params.fieldName = fieldNameOrWhereParams; params.value = value; params.exact = exact; this._whereEquals(params); return; } const whereParams = fieldNameOrWhereParams; if (this._negate) { this._negate = false; this._whereNotEquals(whereParams); return; } whereParams.fieldName = this._ensureValidFieldName(whereParams.fieldName, whereParams.nestedPath); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); if (this._ifValueIsMethod("Equals", whereParams, tokens)) { return; } const transformToEqualValue = this._transformValue(whereParams); const addQueryParameter = this._addQueryParameter(transformToEqualValue); const whereToken = WhereToken_1.WhereToken.create("Equals", whereParams.fieldName, addQueryParameter, new WhereToken_1.WhereOptions({ exact: whereParams.exact })); tokens.push(whereToken); } _ifValueIsMethod(op, whereParams, tokens) { if (whereParams.value instanceof MethodCall_1.MethodCall) { const mc = whereParams.value; const args = mc.args.map(() => null); for (let i = 0; i < mc.args.length; i++) { args[i] = this._addQueryParameter(mc.args[i]); } let token; const type = mc.constructor.name; if (CmpXchg_1.CmpXchg.name === type) { token = WhereToken_1.WhereToken.create(op, whereParams.fieldName, null, new WhereToken_1.WhereOptions({ methodType: "CmpXchg", parameters: args, property: mc.accessPath, exact: whereParams.exact })); } else { (0, Exceptions_1.throwError)("InvalidArgumentException", `Unknown method ${type}.`); } tokens.push(token); return true; } return false; } _whereNotEquals(fieldNameOrWhereParams, value, exact = false) { let whereParams; if (TypeUtil_1.TypeUtil.isString(fieldNameOrWhereParams)) { whereParams = new WhereParams_1.WhereParams(); whereParams.fieldName = fieldNameOrWhereParams; whereParams.value = value; whereParams.exact = exact; return this._whereNotEquals(whereParams); } whereParams = fieldNameOrWhereParams; if (this._negate) { this._negate = false; this._whereEquals(whereParams); return; } const transformToEqualValue = this._transformValue(whereParams); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); whereParams.fieldName = this._ensureValidFieldName(whereParams.fieldName, whereParams.nestedPath); if (this._ifValueIsMethod("NotEquals", whereParams, tokens)) { return; } const whereToken = WhereToken_1.WhereToken.create("NotEquals", whereParams.fieldName, this._addQueryParameter(transformToEqualValue), new WhereToken_1.WhereOptions(whereParams.exact)); tokens.push(whereToken); } _negateNext() { this._negate = !this._negate; } _whereIn(fieldName, values, exact = false) { this._assertMethodIsCurrentlySupported("whereIn"); fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const whereToken = WhereToken_1.WhereToken.create("In", fieldName, this._addQueryParameter(this._transformCollection(fieldName, AbstractDocumentQuery._unpackCollection(values)))); tokens.push(whereToken); } _whereStartsWith(fieldName, value, exact = false) { this._assertMethodIsCurrentlySupported("whereStartsWith"); const whereParams = new WhereParams_1.WhereParams(); whereParams.fieldName = fieldName; whereParams.value = value; whereParams.allowWildcards = true; const transformToEqualValue = this._transformValue(whereParams); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); whereParams.fieldName = this._ensureValidFieldName(whereParams.fieldName, whereParams.nestedPath); this._negateIfNeeded(tokens, whereParams.fieldName); const whereToken = WhereToken_1.WhereToken.create("StartsWith", whereParams.fieldName, this._addQueryParameter(transformToEqualValue), new WhereToken_1.WhereOptions({ exact })); tokens.push(whereToken); } _whereEndsWith(fieldName, value, exact = false) { this._assertMethodIsCurrentlySupported("whereEndsWith"); const whereParams = new WhereParams_1.WhereParams(); whereParams.fieldName = fieldName; whereParams.value = value; whereParams.allowWildcards = true; const transformToEqualValue = this._transformValue(whereParams); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); whereParams.fieldName = this._ensureValidFieldName(whereParams.fieldName, whereParams.nestedPath); this._negateIfNeeded(tokens, whereParams.fieldName); const whereToken = WhereToken_1.WhereToken.create("EndsWith", whereParams.fieldName, this._addQueryParameter(transformToEqualValue), new WhereToken_1.WhereOptions({ exact })); tokens.push(whereToken); } _whereBetween(fieldName, start, end, exact = false) { this._assertMethodIsCurrentlySupported("whereBetween"); fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const startParams = new WhereParams_1.WhereParams(); startParams.value = start; startParams.fieldName = fieldName; const endParams = new WhereParams_1.WhereParams(); endParams.value = end; endParams.fieldName = fieldName; const fromParameterName = this._addQueryParameter(!start ? "*" : this._transformValue(startParams, true)); const toParameterName = this._addQueryParameter(!end ? "NULL" : this._transformValue(endParams, true)); const whereToken = WhereToken_1.WhereToken.create("Between", fieldName, null, new WhereToken_1.WhereOptions({ exact, from: fromParameterName, to: toParameterName })); tokens.push(whereToken); } _whereGreaterThan(fieldName, value, exact = false) { fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const whereParams = new WhereParams_1.WhereParams(); whereParams.value = value; whereParams.fieldName = fieldName; const parameter = this._addQueryParameter(!value ? "*" : this._transformValue(whereParams, true)); const whereToken = WhereToken_1.WhereToken.create("GreaterThan", fieldName, parameter, new WhereToken_1.WhereOptions({ exact })); tokens.push(whereToken); } _whereGreaterThanOrEqual(fieldName, value, exact = false) { fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const whereParams = new WhereParams_1.WhereParams(); whereParams.value = value; whereParams.fieldName = fieldName; const parameter = this._addQueryParameter(!value ? "*" : this._transformValue(whereParams, true)); const whereToken = WhereToken_1.WhereToken.create("GreaterThanOrEqual", fieldName, parameter, new WhereToken_1.WhereOptions({ exact })); tokens.push(whereToken); } _whereLessThan(fieldName, value, exact = false) { fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const whereParams = new WhereParams_1.WhereParams(); whereParams.value = value; whereParams.fieldName = fieldName; const parameter = this._addQueryParameter(!value ? "NULL" : this._transformValue(whereParams, true)); const whereToken = WhereToken_1.WhereToken.create("LessThan", fieldName, parameter, new WhereToken_1.WhereOptions({ exact })); tokens.push(whereToken); } _whereLessThanOrEqual(fieldName, value, exact = false) { fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const whereParams = new WhereParams_1.WhereParams(); whereParams.value = value; whereParams.fieldName = fieldName; const parameter = this._addQueryParameter(!value ? "NULL" : this._transformValue(whereParams, true)); const whereToken = WhereToken_1.WhereToken.create("LessThanOrEqual", fieldName, parameter, new WhereToken_1.WhereOptions({ exact })); tokens.push(whereToken); } _whereRegex(fieldName, pattern) { this._assertMethodIsCurrentlySupported("whereRegex"); fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const whereParams = new WhereParams_1.WhereParams(); whereParams.value = pattern; whereParams.fieldName = fieldName; const parameter = this._addQueryParameter(this._transformValue(whereParams)); const whereToken = WhereToken_1.WhereToken.create("Regex", fieldName, parameter); tokens.push(whereToken); } _andAlso(wrapPreviousQueryClauses = false) { const tokens = this._getCurrentWhereTokens(); if (!tokens || !tokens.length) { return; } if (tokens[tokens.length - 1] instanceof QueryOperatorToken_1.QueryOperatorToken) { (0, Exceptions_1.throwError)("InvalidOperationException", "Cannot add AND, previous token was already an operator token."); } if (wrapPreviousQueryClauses) { tokens.unshift(OpenSubclauseToken_1.OpenSubclauseToken.create()); tokens.push(CloseSubclauseToken_1.CloseSubclauseToken.create()); tokens.push(QueryOperatorToken_1.QueryOperatorToken.AND); } else { tokens.push(QueryOperatorToken_1.QueryOperatorToken.AND); } } _orElse() { const tokens = this._getCurrentWhereTokens(); if (!tokens && !tokens.length) { return; } if (tokens[tokens.length - 1] instanceof QueryOperatorToken_1.QueryOperatorToken) { (0, Exceptions_1.throwError)("InvalidOperationException", "Cannot add OR, previous token was already an operator token."); } tokens.push(QueryOperatorToken_1.QueryOperatorToken.OR); } setFilterMode(on) { return new FilterModeScope(this._filterModeStack, on); } _boost(boost) { this._assertMethodIsCurrentlySupported("boost"); if (boost === 1.0) { return; } if (boost < 0.0) { (0, Exceptions_1.throwError)("InvalidArgumentException", "Boost factor must be a non-negative number"); } const tokens = this._getCurrentWhereTokens(); let last = tokens.length ? tokens[tokens.length - 1] : null; if (last instanceof WhereToken_1.WhereToken) { last.options.boost = boost; } else if (last instanceof CloseSubclauseToken_1.CloseSubclauseToken) { const parameter = this._addQueryParameter(boost); const close = last; let openSubclauseToSkip = 0; let index = tokens.indexOf(last); while (last && index > 0) { index--; last = tokens[index]; if (last instanceof CloseSubclauseToken_1.CloseSubclauseToken) { openSubclauseToSkip++; } else if (last instanceof OpenSubclauseToken_1.OpenSubclauseToken && openSubclauseToSkip > 0) { openSubclauseToSkip--; } else if (last instanceof OpenSubclauseToken_1.OpenSubclauseToken) { last.boostParameterName = parameter; close.boostParameterName = parameter; } } } else { (0, Exceptions_1.throwError)("InvalidOperationException", "Cannot apply boost"); } } _fuzzy(fuzzy) { this._assertMethodIsCurrentlySupported("fuzzy"); const tokens = this._getCurrentWhereTokens(); if (!tokens && !tokens.length) { (0, Exceptions_1.throwError)("InvalidOperationException", "Fuzzy can only be used right after where clause."); } const whereToken = tokens[tokens.length - 1]; if (!(whereToken instanceof WhereToken_1.WhereToken)) { (0, Exceptions_1.throwError)("InvalidOperationException", "Fuzzy can only be used right after where clause."); } if (whereToken.whereOperator !== "Equals") { (0, Exceptions_1.throwError)("InvalidOperationException", "Fuzzy can only be used right after where clause with equals operator"); } if (fuzzy < 0.0 || fuzzy > 1.0) { (0, Exceptions_1.throwError)("InvalidArgumentException", "Fuzzy distance must be between 0.0 and 1.0."); } whereToken.options.fuzzy = fuzzy; } _proximity(proximity) { this._assertMethodIsCurrentlySupported("proximity"); const tokens = this._getCurrentWhereTokens(); if (!tokens && !tokens.length) { (0, Exceptions_1.throwError)("InvalidOperationException", "Proximity can only be used right after search clause."); } const whereToken = tokens[tokens.length - 1]; if (!(whereToken instanceof WhereToken_1.WhereToken)) { (0, Exceptions_1.throwError)("InvalidOperationException", "Proximity can only be used right after search clause."); } if (whereToken.whereOperator !== "Search") { (0, Exceptions_1.throwError)("InvalidOperationException", "Proximity can only be used right after search clause"); } if (proximity < 0) { (0, Exceptions_1.throwError)("InvalidArgumentException", "Proximity distance must be a number greater than or equal to 0"); } whereToken.options.proximity = proximity; } _orderBy(field, orderingOrOptions = "String") { if (TypeUtil_1.TypeUtil.isString(orderingOrOptions)) { this._assertNoRawQuery(); const f = this._ensureValidFieldName(field, false); this._orderByTokens.push(OrderByToken_1.OrderByToken.createAscending(f, { ordering: orderingOrOptions })); } else { const sorterName = orderingOrOptions.sorterName; if (StringUtil_1.StringUtil.isNullOrEmpty(sorterName)) { (0, Exceptions_1.throwError)("InvalidArgumentException", "SorterName cannot be null or empty"); } this._assertNoRawQuery(); const f = this._ensureValidFieldName(field, false); this._orderByTokens.push(OrderByToken_1.OrderByToken.createAscending(f, orderingOrOptions)); } } _orderByDescending(field, orderingOrOptions = "String") { if (TypeUtil_1.TypeUtil.isString(orderingOrOptions)) { this._assertNoRawQuery(); const f = this._ensureValidFieldName(field, false); this._orderByTokens.push(OrderByToken_1.OrderByToken.createDescending(f, { ordering: orderingOrOptions })); } else { const sorterName = orderingOrOptions.sorterName; if (StringUtil_1.StringUtil.isNullOrEmpty(sorterName)) { (0, Exceptions_1.throwError)("InvalidArgumentException", "SorterName cannot be null or empty"); } this._assertNoRawQuery(); const f = this._ensureValidFieldName(field, false); this._orderByTokens.push(OrderByToken_1.OrderByToken.createDescending(f, orderingOrOptions)); } } _orderByScore() { this._assertNoRawQuery(); this._orderByTokens.push(OrderByToken_1.OrderByToken.scoreAscending); } _orderByScoreDescending() { this._assertNoRawQuery(); this._orderByTokens.push(OrderByToken_1.OrderByToken.scoreDescending); } _statistics(statsCallback) { statsCallback(this._queryStats); } _generateIndexQuery(query) { const indexQuery = new IndexQuery_1.IndexQuery(); indexQuery.query = query; indexQuery.start = this._start; indexQuery.waitForNonStaleResults = this._theWaitForNonStaleResults; indexQuery.waitForNonStaleResultsTimeout = this._timeout; indexQuery.queryParameters = this._queryParameters; indexQuery.disableCaching = this._disableCaching; indexQuery.projectionBehavior = this.projectionBehavior; if (this._pageSize) { indexQuery.pageSize = this._pageSize; } return indexQuery; } _search(fieldName, searchTerms, operator = "OR") { this._assertMethodIsCurrentlySupported("search"); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); fieldName = this._ensureValidFieldName(fieldName, false); this._negateIfNeeded(tokens, fieldName); const whereToken = WhereToken_1.WhereToken.create("Search", fieldName, this._addQueryParameter(searchTerms), new WhereToken_1.WhereOptions({ search: operator })); tokens.push(whereToken); } toString(compatibilityMode = false) { if (this._queryRaw) { return this._queryRaw; } if (this._currentClauseDepth) { (0, Exceptions_1.throwError)("InvalidOperationException", "A clause was not closed correctly within this query, current clause depth = " + this._currentClauseDepth); } const queryText = new StringBuilder_1.StringBuilder(); this._buildDeclare(queryText); if (this._graphRawQuery) { this._buildWith(queryText); this._buildGraphQuery(queryText); } else { this._buildFrom(queryText); } this._buildGroupBy(queryText); this._buildWhere(queryText); this._buildOrderBy(queryText); this._buildLoad(queryText); this._buildFilter(queryText); this._buildSelect(queryText); this._buildInclude(queryText); if (!compatibilityMode) { this._buildPagination(queryText); } return queryText.toString(); } _buildGraphQuery(queryText) { this._graphRawQuery.writeTo(queryText); } _buildWith(queryText) { for (const withToken of this._withTokens) { withToken.writeTo(queryText); queryText.append(os.EOL); } } _buildPagination(queryText) { if (this._start > 0 || !TypeUtil_1.TypeUtil.isNullOrUndefined(this._pageSize)) { queryText .append(" limit $") .append(this._addQueryParameter(this._start)) .append(", $") .append(this._addQueryParameter(this._pageSize)); } if (this._filterTokens.length > 0 && this._filterLimit > 0) { queryText .append(" filter_limit $") .append(this._addQueryParameter(this._filterLimit)); } } _buildInclude(queryText) { if (!this._documentIncludes.size && !this._highlightingTokens.length && !this._explanationToken && !this._queryTimings && !this._counterIncludesTokens && !this._revisionsIncludesTokens && !this._timeSeriesIncludesTokens && !this._compareExchangeValueIncludesTokens) { return; } queryText.append(" include "); const firstRef = { value: true }; for (const include of this._documentIncludes) { if (!firstRef.value) { queryText.append(","); } firstRef.value = false; let escapedInclude; if (IncludesUtil_1.IncludesUtil.requiresQuotes(include, x => escapedInclude = x)) { queryText.append("'"); queryText.append(escapedInclude); queryText.append("'"); } else { queryText.append(include); } } this._writeIncludeTokens(this._counterIncludesTokens, firstRef, queryText); this._writeIncludeTokens(this._timeSeriesIncludesTokens, firstRef, queryText); this._writeIncludeTokens(this._revisionsIncludesTokens, firstRef, queryText); this._writeIncludeTokens(this._compareExchangeValueIncludesTokens, firstRef, queryText); this._writeIncludeTokens(this._highlightingTokens, firstRef, queryText); if (this._explanationToken) { if (!firstRef.value) { queryText.append(","); } firstRef.value = false; this._explanationToken.writeTo(queryText); } if (this._queryTimings) { if (!firstRef.value) { queryText.append(","); } firstRef.value = false; TimingsToken_1.TimingsToken.instance.writeTo(queryText); } } _writeIncludeTokens(tokens, firstRef, queryText) { if (!tokens) { return; } for (const token of tokens) { if (!firstRef.value) { queryText.append(","); } firstRef.value = false; token.writeTo(queryText); } } _intersect() { const tokens = this._getCurrentWhereTokens(); if (tokens.length > 0) { const last = tokens[tokens.length - 1]; if (last instanceof WhereToken_1.WhereToken || last instanceof CloseSubclauseToken_1.CloseSubclauseToken) { this._isIntersect = true; tokens.push(IntersectMarkerToken_1.IntersectMarkerToken.INSTANCE); return; } } (0, Exceptions_1.throwError)("InvalidOperationException", "Cannot add INTERSECT at this point."); } _whereExists(fieldName) { fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, null); tokens.push(WhereToken_1.WhereToken.create("Exists", fieldName, null)); } _containsAny(fieldName, values) { this._assertMethodIsCurrentlySupported("containsAny"); fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const array = this._transformCollection(fieldName, AbstractDocumentQuery._unpackCollection(values)); const whereToken = WhereToken_1.WhereToken.create("In", fieldName, this._addQueryParameter(array), new WhereToken_1.WhereOptions({ exact: false })); tokens.push(whereToken); } _containsAll(fieldName, values) { this._assertMethodIsCurrentlySupported("containsAll"); fieldName = this._ensureValidFieldName(fieldName, false); const tokens = this._getCurrentWhereTokens(); this._appendOperatorIfNeeded(tokens); this._negateIfNeeded(tokens, fieldName); const array = this._transformCollection(fieldName, AbstractDocumentQuery._unpackCollection(values)); if (!array.length) { tokens.push(TrueToken_1.TrueToken.INSTANCE); return; } const whereToken = WhereToken_1.WhereToken.create("AllIn", fieldName, this._addQueryParameter(array)); tokens.push(whereToken); } addRootType(clazz) { this._rootTypes.add(clazz); } _distinct() { if (this.isDistinct) { (0, Exceptions_1.throwError)("InvalidOperationException", "This is already a distinct query."); } if (!this._selectTokens.length) { this._selectTokens.push(DistinctToken_1.DistinctToken.INSTANCE); } else { this._selectTokens.unshift(DistinctToken_1.DistinctToken.INSTANCE); } } _updateStatsAndHighlightingsAndExplanations(queryResult) { this._queryStats.updateQueryStats(queryResult); this._queryHighlightings.update(queryResult); if (this._explanations) { this._explanations.update(queryResult); } if (this._queryTimings) { this._queryTimings.update(queryResult); } } _buildSelect(writer) { if (!this._selectTokens || !this._selectTokens.length) { return; } writer.append(" select "); if (this._selectTokens.length === 1 && this._selectTokens[0] instanceof DistinctToken_1.DistinctToken) { this._selectTokens[0].writeTo(writer); writer.append(" *"); return; } for (let i = 0; i < this._selectTokens.length; i++) { const token = this._selectTokens[i]; if (i > 0 && !(this._selectTokens[i - 1] instanceof DistinctToken_1.DistinctToken)) { writer.append(","); } DocumentQueryHelper_1.DocumentQueryHelper.addSpaceIfNeeded(i > 0 ? this._selectTokens[i - 1] : null, token, writer); token.writeTo(writer); } } _buildFrom(writer) { this._fromToken.writeTo(writer); } _buildDeclare(writer) { if (!this._declareTokens) { return; } for (const token of this._declareTokens) { token.writeTo(writer); } } _buildLoad(writer) { if (!this._lo