@orama/plugin-pt15 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../../orama/src/components/tokenizer/languages.ts","../../orama/src/utils.ts","../../orama/src/errors.ts","../../orama/src/components/defaults.ts","../../orama/src/components/internal-document-id-store.ts","../../orama/src/components/index.ts","../../orama/src/trees/avl.ts","../../orama/src/trees/flat.ts","../../orama/src/components/levenshtein.ts","../../orama/src/trees/radix.ts","../../orama/src/trees/bkd.ts","../../orama/src/trees/bool.ts","../../orama/src/components/algorithms.ts","../../orama/src/trees/vector.ts","../../orama/src/components/tokenizer/english-stemmer.ts","../src/algorithm.ts"],"sourcesContent":["import type { AnyOrama, SearchableType, IIndex, SearchableValue, Tokenizer, OnlyStrings, FlattenSchemaProperty, TokenScore, WhereCondition, OramaPluginSync, AnySchema, ObjectComponents, BM25Params } from '@orama/orama'\nimport {\n index as Index, internalDocumentIDStore } from '@orama/orama/components'\nimport { PT15IndexStore, insertString, recursiveCreate, PositionsStorage, searchString, removeString } from './algorithm.js';\n\ntype InternalDocumentID = internalDocumentIDStore.InternalDocumentID;\ntype InternalDocumentIDStore = internalDocumentIDStore.InternalDocumentIDStore;\ntype DocumentID = internalDocumentIDStore.DocumentID;\n\nexport function pluginPT15(): OramaPluginSync {\n\n return {\n name: 'orama-plugin-pt15',\n\n getComponents: function getComponents(schema: AnySchema) {\n return createComponents(schema)\n },\n }\n}\n\nfunction createComponents(schema: AnySchema): Partial<ObjectComponents<any, any, any>> {\n return {\n index: {\n create: function create() {\n const indexDatastore: PT15IndexStore = {\n indexes: {},\n vectorIndexes: {},\n searchableProperties: [],\n searchablePropertiesWithTypes: {},\n }\n\n recursiveCreate(indexDatastore, schema, '')\n\n return indexDatastore\n },\n insert: function insert(\n implementation: IIndex<PT15IndexStore>,\n indexDatastorage: PT15IndexStore,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n ) {\n if (!(schemaType === 'string' || schemaType === 'string[]')) {\n return Index.insert(implementation as unknown as IIndex<Index.Index>, indexDatastorage as unknown as Index.Index, prop, id, internalId, value, schemaType, language, tokenizer, docsCount)\n }\n\n const storage = indexDatastorage.indexes[prop].node as PositionsStorage\n\n if (Array.isArray(value)) {\n for (const item of value) {\n insertString(\n item as string,\n storage,\n prop,\n internalId,\n language,\n tokenizer,\n )\n }\n } else {\n insertString(\n value as string,\n storage,\n prop,\n internalId,\n language,\n tokenizer,\n )\n }\n },\n // remove: <T extends I>(implementation: IIndex<T>, index: T, prop: string, id: DocumentID, value: SearchableValue, schemaType: SearchableType, language: string | undefined, tokenizer: Tokenizer, docsCount: number) => SyncOrAsyncValue<boolean>;\n remove: function remove(implementation: IIndex<PT15IndexStore>, indexDatastorage: PT15IndexStore, prop: string, id: DocumentID, internalId: InternalDocumentID, value: SearchableValue, schemaType: SearchableType, language: string | undefined, tokenizer: Tokenizer, docsCount: number) {\n if (!(schemaType === 'string' || schemaType === 'string[]')) {\n return Index.remove(implementation as IIndex<Index.Index>, indexDatastorage as Index.Index, prop, id, internalId, value, schemaType, language, tokenizer, docsCount)\n }\n\n const storage = indexDatastorage.indexes[prop].node as PositionsStorage\n\n if (Array.isArray(value)) {\n for (const item of value) {\n removeString(\n item as string,\n storage,\n prop,\n internalId,\n tokenizer,\n language\n )\n }\n } else {\n removeString(\n value as string,\n storage,\n prop,\n internalId,\n tokenizer,\n language\n )\n }\n\n return true\n },\n insertDocumentScoreParameters: () => {throw new Error()},\n insertTokenScoreParameters: () => {throw new Error()},\n removeDocumentScoreParameters: () => {throw new Error()},\n removeTokenScoreParameters: () => {throw new Error()},\n calculateResultScores: () => {throw new Error()},\n search: function search<T extends AnyOrama>(index: PT15IndexStore, term: string, tokenizer: Tokenizer, language: string | undefined, propertiesToSearch: string[], exact: boolean, tolerance: number, boost: Partial<Record<OnlyStrings<FlattenSchemaProperty<T>[]>, number>>, relevance: Required<BM25Params>, docsCount: number, whereFiltersIDs: Set<InternalDocumentID> | undefined): TokenScore[] {\n if (tolerance !== 0) {\n throw new Error('Tolerance not implemented yet')\n }\n if (exact === true) {\n throw new Error('Exact not implemented yet')\n }\n\n const maps: Map<number, number>[] = []\n const propertyLength = propertiesToSearch.length\n let max = {\n score: -Infinity,\n id: -1\n }\n for (let i = 0; i < propertyLength; i++) {\n const property = propertiesToSearch[i]\n const storage = index.indexes[property].node as PositionsStorage\n const boostPerProp = boost[property] ?? 1\n const map = searchString(tokenizer, term, storage, boostPerProp, whereFiltersIDs);\n if (map.size > max.score) {\n max = {\n score: map.size,\n id: i\n }\n }\n maps.push(map)\n }\n\n if (maps.length === 1) {\n return Array.from(maps[0])\n }\n\n const base = maps[max.id]\n for (let i = 0; i < maps.length; i++) {\n if (i === max.id) {\n continue\n }\n\n const map = maps[i]\n for (const [id, score] of map) {\n if (base.has(id)) {\n base.set(id, base.get(id)! + score)\n } else {\n base.set(id, score)\n }\n }\n }\n \n return Array.from(base)\n },\n searchByWhereClause: function searchByWhereClause<T extends AnyOrama>(index: PT15IndexStore, tokenizer: Tokenizer, filters: Partial<WhereCondition<T['schema']>>, language: string | undefined) {\n const stringFiltersList = Object.entries(filters).filter(([propName]) => index.indexes[propName].type === 'Position')\n\n // PT15 doen't support string filters.\n // this plugin doesn't distringuish between prefix and exact match.\n if (stringFiltersList.length !== 0) {\n throw new Error('String filters are not supported')\n }\n\n return Index.searchByWhereClause(index as Index.Index, tokenizer, filters, language)\n },\n getSearchableProperties: function getSearchableProperties(index: PT15IndexStore): string[] {\n return index.searchableProperties\n },\n getSearchablePropertiesWithTypes: function (index: PT15IndexStore) {\n return index.searchablePropertiesWithTypes\n },\n load: function load<R = unknown>(sharedInternalDocumentStore: InternalDocumentIDStore, raw: R): PT15IndexStore {\n const dump1 = Index.load(sharedInternalDocumentStore, raw[0])\n const dump2 = raw[1]\n return {\n ...dump1,\n indexes: {\n ...Object.fromEntries(dump2),\n ...dump1.indexes\n } as PT15IndexStore['indexes']\n }\n },\n save: function save<R = unknown>(index: PT15IndexStore): R {\n const baseIndex = index as unknown as Index.Index\n const nonStringIndexes = Object.entries(index.indexes).filter(([, { type }]) => type !== 'Position')\n const dump1 = Index.save({\n ...baseIndex,\n indexes: Object.fromEntries(nonStringIndexes) as Index.Index['indexes']\n })\n\n const stringIndexes = Object.entries(index.indexes).filter(([, { type }]) => type === 'Position')\n\n return [dump1, stringIndexes] as unknown as R\n }\n }\n }\n}\n","export const STEMMERS: Record<string, string> = {\n arabic: 'ar',\n armenian: 'am',\n bulgarian: 'bg',\n danish: 'dk',\n dutch: 'nl',\n english: 'en',\n finnish: 'fi',\n french: 'fr',\n german: 'de',\n greek: 'gr',\n hungarian: 'hu',\n indian: 'in',\n indonesian: 'id',\n irish: 'ie',\n italian: 'it',\n lithuanian: 'lt',\n nepali: 'np',\n norwegian: 'no',\n portuguese: 'pt',\n romanian: 'ro',\n russian: 'ru',\n serbian: 'rs',\n slovenian: 'ru',\n spanish: 'es',\n swedish: 'se',\n tamil: 'ta',\n turkish: 'tr',\n ukrainian: 'uk',\n sanskrit: 'sk'\n}\n\nexport const SPLITTERS: Record<Language, RegExp> = {\n dutch: /[^A-Za-zàèéìòóù0-9_'-]+/gim,\n english: /[^A-Za-zàèéìòóù0-9_'-]+/gim,\n french: /[^a-z0-9äâàéèëêïîöôùüûœç-]+/gim,\n italian: /[^A-Za-zàèéìòóù0-9_'-]+/gim,\n norwegian: /[^a-z0-9_æøåÆØÅäÄöÖüÜ]+/gim,\n portuguese: /[^a-z0-9à-úÀ-Ú]/gim,\n russian: /[^a-z0-9а-яА-ЯёЁ]+/gim,\n spanish: /[^a-z0-9A-Zá-úÁ-ÚñÑüÜ]+/gim,\n swedish: /[^a-z0-9_åÅäÄöÖüÜ-]+/gim,\n german: /[^a-z0-9A-ZäöüÄÖÜß]+/gim,\n finnish: /[^a-z0-9äöÄÖ]+/gim,\n danish: /[^a-z0-9æøåÆØÅ]+/gim,\n hungarian: /[^a-z0-9áéíóöőúüűÁÉÍÓÖŐÚÜŰ]+/gim,\n romanian: /[^a-z0-9ăâîșțĂÂÎȘȚ]+/gim,\n serbian: /[^a-z0-9čćžšđČĆŽŠĐ]+/gim,\n turkish: /[^a-z0-9çÇğĞıİöÖşŞüÜ]+/gim,\n lithuanian: /[^a-z0-9ąčęėįšųūžĄČĘĖĮŠŲŪŽ]+/gim,\n arabic: /[^a-z0-9أ-ي]+/gim,\n nepali: /[^a-z0-9अ-ह]+/gim,\n irish: /[^a-z0-9áéíóúÁÉÍÓÚ]+/gim,\n indian: /[^a-z0-9अ-ह]+/gim,\n armenian: /[^a-z0-9ա-ֆ]+/gim,\n greek: /[^a-z0-9α-ωά-ώ]+/gim,\n indonesian: /[^a-z0-9]+/gim,\n ukrainian: /[^a-z0-9а-яА-ЯіїєІЇЄ]+/gim,\n slovenian: /[^a-z0-9螚ȎŠ]+/gim,\n bulgarian: /[^a-z0-9а-яА-Я]+/gim,\n tamil: /[^a-z0-9அ-ஹ]+/gim,\n sanskrit: /[^a-z0-9A-Zāīūṛḷṃṁḥśṣṭḍṇṅñḻḹṝ]+/gim\n}\n\nexport const SUPPORTED_LANGUAGES = Object.keys(STEMMERS)\n\nexport function getLocale(language: string | undefined) {\n return language !== undefined && SUPPORTED_LANGUAGES.includes(language) ? STEMMERS[language] : undefined\n}\n\nexport type Language = (typeof SUPPORTED_LANGUAGES)[number]\n","import type { AnyDocument, GeosearchDistanceUnit, Optional, Results, SearchableValue, TokenScore } from './types.js'\nimport { createError } from './errors.js'\n\nconst baseId = Date.now().toString().slice(5)\nlet lastId = 0\n\nconst k = 1024\nconst nano = BigInt(1e3)\nconst milli = BigInt(1e6)\nconst second = BigInt(1e9)\n\nexport const isServer = typeof window === 'undefined'\n\n/**\n * This value can be increased up to 100_000\n * But i don't know if this value change from nodejs to nodejs\n * So I will keep a safer value here.\n */\nexport const MAX_ARGUMENT_FOR_STACK = 65535\n\n/**\n * This method is needed to used because of issues like: https://github.com/askorama/orama/issues/301\n * that issue is caused because the array that is pushed is huge (>100k)\n *\n * @example\n * ```ts\n * safeArrayPush(myArray, [1, 2])\n * ```\n */\nexport function safeArrayPush<T>(arr: T[], newArr: T[]): void {\n if (newArr.length < MAX_ARGUMENT_FOR_STACK) {\n Array.prototype.push.apply(arr, newArr)\n } else {\n const newArrLength = newArr.length\n for (let i = 0; i < newArrLength; i += MAX_ARGUMENT_FOR_STACK) {\n Array.prototype.push.apply(arr, newArr.slice(i, i + MAX_ARGUMENT_FOR_STACK))\n }\n }\n}\n\nexport function sprintf(template: string, ...args: Array<string | number>): string {\n return template.replace(\n /%(?:(?<position>\\d+)\\$)?(?<width>-?\\d*\\.?\\d*)(?<type>[dfs])/g,\n function (...replaceArgs: Array<string | number | Record<string, string>>): string {\n const groups = replaceArgs[replaceArgs.length - 1] as Record<string, string>\n const { width: rawWidth, type, position } = groups\n\n const replacement = position ? args[Number.parseInt(position) - 1]! : args.shift()!\n const width = rawWidth === '' ? 0 : Number.parseInt(rawWidth)\n\n switch (type) {\n case 'd':\n return replacement.toString().padStart(width, '0')\n case 'f': {\n let value = replacement\n const [padding, precision] = rawWidth.split('.').map((w) => Number.parseFloat(w))\n\n if (typeof precision === 'number' && precision >= 0) {\n value = (value as number).toFixed(precision)\n }\n\n return typeof padding === 'number' && padding >= 0 ? value.toString().padStart(width, '0') : value.toString()\n }\n case 's':\n return width < 0\n ? (replacement as string).toString().padEnd(-width, ' ')\n : (replacement as string).toString().padStart(width, ' ')\n\n default:\n return replacement as string\n }\n }\n )\n}\n\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) {\n return '0 Bytes'\n }\n const dm = decimals < 0 ? 0 : decimals\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`\n}\n\nexport function isInsideWebWorker(): boolean {\n // @ts-expect-error - WebWorker global scope\n return typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope\n}\n\nexport function isInsideNode(): boolean {\n return typeof process !== 'undefined' && process.release && process.release.name === 'node'\n}\n\nexport function getNanosecondTimeViaPerformance() {\n return BigInt(Math.floor(performance.now() * 1e6))\n}\n\nexport function formatNanoseconds(value: number | bigint): string {\n if (typeof value === 'number') {\n value = BigInt(value)\n }\n\n if (value < nano) {\n return `${value}ns`\n } else if (value < milli) {\n return `${value / nano}μs`\n } else if (value < second) {\n return `${value / milli}ms`\n }\n\n return `${value / second}s`\n}\n\nexport function getNanosecondsTime(): bigint {\n if (isInsideWebWorker()) {\n return getNanosecondTimeViaPerformance()\n }\n\n if (isInsideNode()) {\n return process.hrtime.bigint()\n }\n\n if (typeof process !== 'undefined' && typeof process?.hrtime?.bigint === 'function') {\n return process.hrtime.bigint()\n }\n\n if (typeof performance !== 'undefined') {\n return getNanosecondTimeViaPerformance()\n }\n\n // @todo: fallback to V8 native method to get microtime\n return BigInt(0)\n}\n\nexport function uniqueId(): string {\n return `${baseId}-${lastId++}`\n}\n\nexport function getOwnProperty<T = unknown>(object: Record<string, T>, property: string): T | undefined {\n // Checks if `hasOwn` method is defined avoiding errors with older Node.js versions\n if (Object.hasOwn === undefined) {\n return Object.prototype.hasOwnProperty.call(object, property) ? object[property] : undefined\n }\n\n return Object.hasOwn(object, property) ? object[property] : undefined\n}\n\nexport function getTokenFrequency(token: string, tokens: string[]): number {\n let count = 0\n\n for (const t of tokens) {\n if (t === token) {\n count++\n }\n }\n\n return count\n}\n\nexport function insertSortedValue(\n arr: TokenScore[],\n el: TokenScore,\n compareFn = sortTokenScorePredicate\n): TokenScore[] {\n let low = 0\n let high = arr.length\n let mid\n\n while (low < high) {\n mid = (low + high) >>> 1\n if (compareFn(el, arr[mid]) < 0) {\n high = mid\n } else {\n low = mid + 1\n }\n }\n\n arr.splice(low, 0, el)\n\n return arr\n}\n\nexport function sortTokenScorePredicate(a: TokenScore, b: TokenScore): number {\n if (b[1] === a[1]) {\n return a[0] - b[0]\n }\n\n return b[1] - a[1]\n}\n\n// Intersection function taken from https://github.com/lovasoa/fast_array_intersect.\n// MIT Licensed at the time of writing.\nexport function intersect<T>(arrays: Array<readonly T[]>): T[] {\n if (arrays.length === 0) {\n return []\n } else if (arrays.length === 1) {\n return arrays[0] as T[]\n }\n\n for (let i = 1; i < arrays.length; i++) {\n if (arrays[i].length < arrays[0].length) {\n const tmp = arrays[0]\n arrays[0] = arrays[i]\n arrays[i] = tmp\n }\n }\n\n const set = new Map()\n for (const elem of arrays[0]) {\n set.set(elem, 1)\n }\n for (let i = 1; i < arrays.length; i++) {\n let found = 0\n for (const elem of arrays[i]) {\n const count = set.get(elem)\n if (count === i) {\n set.set(elem, count + 1)\n found++\n }\n }\n if (found === 0) return []\n }\n\n return arrays[0].filter((e) => {\n const count = set.get(e)\n if (count !== undefined) set.set(e, 0)\n return count === arrays.length\n })\n}\n\nexport function getDocumentProperties(doc: AnyDocument, paths: string[]): Record<string, SearchableValue> {\n const properties: Record<string, SearchableValue> = {}\n\n const pathsLength = paths.length\n for (let i = 0; i < pathsLength; i++) {\n const path = paths[i]\n const pathTokens = path.split('.')\n\n let current: SearchableValue | AnyDocument | undefined = doc\n const pathTokensLength = pathTokens.length\n for (let j = 0; j < pathTokensLength; j++) {\n current = current[pathTokens[j]!]\n\n // We found an object but we were supposed to be done\n if (typeof current === 'object') {\n if (\n current !== null &&\n 'lat' in current &&\n 'lon' in current &&\n typeof current.lat === 'number' &&\n typeof current.lon === 'number'\n ) {\n current = properties[path] = current as SearchableValue\n break\n } else if (!Array.isArray(current) && current !== null && j === pathTokensLength - 1) {\n current = undefined\n break\n }\n } else if ((current === null || typeof current !== 'object') && j < pathTokensLength - 1) {\n // We can't recurse anymore but we were supposed to\n current = undefined\n break\n }\n }\n\n if (typeof current !== 'undefined') {\n properties[path] = current as SearchableValue\n }\n }\n\n return properties\n}\n\nexport function getNested<T = SearchableValue>(obj: object, path: string): Optional<T> {\n const props = getDocumentProperties(obj as AnyDocument, [path])\n\n return props[path] as T | undefined\n}\n\nexport function flattenObject(obj: object, prefix = ''): AnyDocument {\n const result: AnyDocument = {}\n\n for (const key in obj) {\n const prop = `${prefix}${key}`\n const objKey = (obj as AnyDocument)[key]\n\n if (typeof objKey === 'object' && objKey !== null) {\n Object.assign(result, flattenObject(objKey, `${prop}.`))\n } else {\n result[prop] = objKey\n }\n }\n return result\n}\n\nconst mapDistanceToMeters = {\n cm: 0.01,\n m: 1,\n km: 1000,\n ft: 0.3048,\n yd: 0.9144,\n mi: 1609.344\n}\n\nexport function convertDistanceToMeters(distance: number, unit: GeosearchDistanceUnit): number {\n const ratio = mapDistanceToMeters[unit]\n\n if (ratio === undefined) {\n throw new Error(createError('INVALID_DISTANCE_SUFFIX', distance).message)\n }\n\n return distance * ratio\n}\n\nexport function removeVectorsFromHits(searchResult: Results<AnyDocument>, vectorProperties: string[]): void {\n searchResult.hits = searchResult.hits.map((result) => ({\n ...result,\n document: {\n ...result.document,\n // Remove embeddings from the result\n ...vectorProperties.reduce((acc, prop) => {\n const path = prop.split('.')\n const lastKey = path.pop()!\n let obj = acc\n for (const key of path) {\n obj[key] = obj[key] ?? {}\n obj = obj[key] as any\n }\n obj[lastKey] = null\n return acc\n }, result.document)\n }\n }))\n}\n\nexport function isPromise(obj: any): obj is Promise<unknown> {\n return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'\n}\n\nexport function isAsyncFunction(func: any): boolean {\n return func?.constructor?.name === 'AsyncFunction'\n}\n\n\nconst withIntersection = 'intersection' in (new Set());\nexport function setIntersection<V>(...sets: Set<V>[]): Set<V> {\n // Fast path 1\n if (sets.length === 0) {\n return new Set();\n }\n // Fast path 2\n if (sets.length === 1) {\n return sets[0];\n }\n // Fast path 3\n if (sets.length === 2) {\n const set1 = sets[0];\n const set2 = sets[1];\n\n if (withIntersection) {\n return set1.intersection(set2);\n }\n const result = new Set<V>();\n const base = set1.size < set2.size ? set1 : set2;\n const other = base === set1 ? set2 : set1;\n for (const value of base) {\n if (other.has(value)) {\n result.add(value);\n }\n }\n return result;\n }\n\n // Slow path\n // Find the smallest set\n const min = {\n index: 0,\n size: sets[0].size,\n }\n for (let i = 1; i < sets.length; i++) {\n if (sets[i].size < min.size) {\n min.index = i;\n min.size = sets[i].size;\n }\n }\n\n if (withIntersection) {\n let base = sets[min.index];\n for (let i = 0; i < sets.length; i++) {\n if (i === min.index) {\n continue;\n }\n base = base.intersection(sets[i]);\n }\n\n return base;\n }\n\n // manual implementation:\n // intersect all sets with the smallest set\n const base = sets[min.index];\n for (let i = 0; i < sets.length; i++) {\n if (i === min.index) {\n continue;\n }\n const other = sets[i];\n for (const value of base) {\n if (!other.has(value)) {\n base.delete(value);\n }\n }\n }\n\n return base;\n}\n\nconst withUnion = 'union' in (new Set());\nexport function setUnion<V>(set1: Set<V> | undefined, set2: Set<V>) {\n if (withUnion) {\n if (set1) {\n return set1.union(set2);\n }\n return set2;\n }\n\n if (!set1) {\n return new Set(set2);\n }\n return new Set([...set1, ...set2]);\n}\n","import { SUPPORTED_LANGUAGES } from './components/tokenizer/languages.js'\nimport { sprintf } from './utils.js'\n\nconst allLanguages = SUPPORTED_LANGUAGES.join('\\n - ')\n\nconst errors = {\n NO_LANGUAGE_WITH_CUSTOM_TOKENIZER: 'Do not pass the language option to create when using a custom tokenizer.',\n LANGUAGE_NOT_SUPPORTED: `Language \"%s\" is not supported.\\nSupported languages are:\\n - ${allLanguages}`,\n INVALID_STEMMER_FUNCTION_TYPE: `config.stemmer property must be a function.`,\n MISSING_STEMMER: `As of version 1.0.0 @orama/orama does not ship non English stemmers by default. To solve this, please explicitly import and specify the \"%s\" stemmer from the package @orama/stemmers. See https://docs.oramasearch.com/open-source/text-analysis/stemming for more information.`,\n CUSTOM_STOP_WORDS_MUST_BE_FUNCTION_OR_ARRAY: 'Custom stop words array must only contain strings.',\n UNSUPPORTED_COMPONENT: `Unsupported component \"%s\".`,\n COMPONENT_MUST_BE_FUNCTION: `The component \"%s\" must be a function.`,\n COMPONENT_MUST_BE_FUNCTION_OR_ARRAY_FUNCTIONS: `The component \"%s\" must be a function or an array of functions.`,\n INVALID_SCHEMA_TYPE: `Unsupported schema type \"%s\" at \"%s\". Expected \"string\", \"boolean\" or \"number\" or array of them.`,\n DOCUMENT_ID_MUST_BE_STRING: `Document id must be of type \"string\". Got \"%s\" instead.`,\n DOCUMENT_ALREADY_EXISTS: `A document with id \"%s\" already exists.`,\n DOCUMENT_DOES_NOT_EXIST: `A document with id \"%s\" does not exists.`,\n MISSING_DOCUMENT_PROPERTY: `Missing searchable property \"%s\".`,\n INVALID_DOCUMENT_PROPERTY: `Invalid document property \"%s\": expected \"%s\", got \"%s\"`,\n UNKNOWN_INDEX: `Invalid property name \"%s\". Expected a wildcard string (\"*\") or array containing one of the following properties: %s`,\n INVALID_BOOST_VALUE: `Boost value must be a number greater than, or less than 0.`,\n INVALID_FILTER_OPERATION: `You can only use one operation per filter, you requested %d.`,\n SCHEMA_VALIDATION_FAILURE: `Cannot insert document due schema validation failure on \"%s\" property.`,\n INVALID_SORT_SCHEMA_TYPE: `Unsupported sort schema type \"%s\" at \"%s\". Expected \"string\" or \"number\".`,\n CANNOT_SORT_BY_ARRAY: `Cannot configure sort for \"%s\" because it is an array (%s).`,\n UNABLE_TO_SORT_ON_UNKNOWN_FIELD: `Unable to sort on unknown field \"%s\". Allowed fields: %s`,\n SORT_DISABLED: `Sort is disabled. Please read the documentation at https://docs.oramasearch for more information.`,\n UNKNOWN_GROUP_BY_PROPERTY: `Unknown groupBy property \"%s\".`,\n INVALID_GROUP_BY_PROPERTY: `Invalid groupBy property \"%s\". Allowed types: \"%s\", but given \"%s\".`,\n UNKNOWN_FILTER_PROPERTY: `Unknown filter property \"%s\".`,\n INVALID_VECTOR_SIZE: `Vector size must be a number greater than 0. Got \"%s\" instead.`,\n INVALID_VECTOR_VALUE: `Vector value must be a number greater than 0. Got \"%s\" instead.`,\n INVALID_INPUT_VECTOR: `Property \"%s\" was declared as a %s-dimensional vector, but got a %s-dimensional vector instead.\\nInput vectors must be of the size declared in the schema, as calculating similarity between vectors of different sizes can lead to unexpected results.`,\n WRONG_SEARCH_PROPERTY_TYPE: `Property \"%s\" is not searchable. Only \"string\" properties are searchable.`,\n FACET_NOT_SUPPORTED: `Facet doens't support the type \"%s\".`,\n INVALID_DISTANCE_SUFFIX: `Invalid distance suffix \"%s\". Valid suffixes are: cm, m, km, mi, yd, ft.`,\n INVALID_SEARCH_MODE: `Invalid search mode \"%s\". Valid modes are: \"fulltext\", \"vector\", \"hybrid\".`,\n MISSING_VECTOR_AND_SECURE_PROXY: `No vector was provided and no secure proxy was configured. Please provide a vector or configure an Orama Secure Proxy to perform hybrid search.`,\n MISSING_TERM: `\"term\" is a required parameter when performing hybrid search. Please provide a search term.`,\n INVALID_VECTOR_INPUT: `Invalid \"vector\" property. Expected an object with \"value\" and \"property\" properties, but got \"%s\" instead.`,\n PLUGIN_CRASHED: `A plugin crashed during initialization. Please check the error message for more information:`,\n PLUGIN_SECURE_PROXY_NOT_FOUND: `Could not find '@orama/secure-proxy-plugin' installed in your Orama instance.\\nPlease install it before proceeding with creating an answer session.\\nRead more at https://docs.orama.com/open-source/plugins/plugin-secure-proxy\\n`,\n PLUGIN_SECURE_PROXY_MISSING_CHAT_MODEL: `Could not find a chat model defined in the secure proxy plugin configuration.\\nPlease provide a chat model before proceeding with creating an answer session.\\nRead more at https://docs.orama.com/open-source/plugins/plugin-secure-proxy\\n`,\n ANSWER_SESSION_LAST_MESSAGE_IS_NOT_ASSISTANT: `The last message in the session is not an assistant message. Cannot regenerate non-assistant messages.`,\n PLUGIN_COMPONENT_CONFLICT: `The component \"%s\" is already defined. The plugin \"%s\" is trying to redefine it.`,\n}\n\nexport type ErrorCode = keyof typeof errors\n\nexport interface OramaError extends Error {\n code: string\n}\n\nexport function createError(code: ErrorCode, ...args: Array<string | number>): OramaError {\n const error = new Error(sprintf(errors[code] ?? `Unsupported Orama Error code: ${code}`, ...args)) as OramaError\n error.code = code\n if ('captureStackTrace' in Error.prototype) {\n Error.captureStackTrace(error)\n }\n\n return error\n}\n","import type { Optional } from '../types.js'\nimport { createError } from '../errors.js'\nimport { Point } from '../trees/bkd.js'\nimport {\n AnyDocument,\n AnyOrama,\n ArraySearchableType,\n ElapsedTime,\n ScalarSearchableType,\n SearchableType,\n TypedDocument,\n Vector\n} from '../types.js'\nimport { formatNanoseconds, uniqueId } from '../utils.js'\n\nexport { getDocumentProperties } from '../utils.js'\n\nexport function formatElapsedTime(n: bigint): ElapsedTime {\n return {\n raw: Number(n),\n formatted: formatNanoseconds(n)\n }\n}\n\nexport function getDocumentIndexId(doc: AnyDocument): string {\n if (doc.id) {\n if (typeof doc.id !== 'string') {\n throw createError('DOCUMENT_ID_MUST_BE_STRING', typeof doc.id)\n }\n\n return doc.id\n }\n\n return uniqueId()\n}\n\nexport function validateSchema<T extends AnyOrama, ResultDocument extends TypedDocument<T>>(\n doc: ResultDocument,\n schema: T['schema']\n): Optional<string> {\n for (const [prop, type] of Object.entries(schema)) {\n const value = doc[prop]\n\n if (typeof value === 'undefined') {\n continue\n }\n\n if (\n type === 'geopoint' &&\n typeof value === 'object' &&\n typeof value.lon === 'number' &&\n typeof value.lat === 'number'\n ) {\n continue\n }\n\n if (type === 'enum' && (typeof value === 'string' || typeof value === 'number')) {\n continue\n }\n if (type === 'enum[]' && Array.isArray(value)) {\n const valueLength = value.length\n for (let i = 0; i < valueLength; i++) {\n if (typeof value[i] !== 'string' && typeof value[i] !== 'number') {\n return prop + '.' + i\n }\n }\n continue\n }\n\n if (isVectorType(type)) {\n const vectorSize = getVectorSize(type)\n if (!Array.isArray(value) || value.length !== vectorSize) {\n throw createError('INVALID_INPUT_VECTOR', prop, vectorSize, value.length)\n }\n continue\n }\n\n if (isArrayType(type)) {\n if (!Array.isArray(value)) {\n return prop\n }\n const expectedType = getInnerType(type)\n\n const valueLength = value.length\n for (let i = 0; i < valueLength; i++) {\n if (typeof value[i] !== expectedType) {\n return prop + '.' + i\n }\n }\n\n continue\n }\n\n if (typeof type === 'object') {\n if (!value || typeof value !== 'object') {\n return prop\n }\n\n // using as ResultDocument is not exactly right but trying to be type-safe here is not useful\n const subProp = validateSchema(value as ResultDocument, type)\n if (subProp) {\n return prop + '.' + subProp\n }\n continue\n }\n\n if (typeof value !== type) {\n return prop\n }\n }\n\n return undefined\n}\n\nconst IS_ARRAY_TYPE: Record<SearchableType, boolean> = {\n string: false,\n number: false,\n boolean: false,\n enum: false,\n geopoint: false,\n 'string[]': true,\n 'number[]': true,\n 'boolean[]': true,\n 'enum[]': true\n}\n\nconst INNER_TYPE: Record<ArraySearchableType, ScalarSearchableType> = {\n 'string[]': 'string',\n 'number[]': 'number',\n 'boolean[]': 'boolean',\n 'enum[]': 'enum'\n}\n\nexport function isGeoPointType(type: unknown): type is Point {\n return type === 'geopoint'\n}\n\nexport function isVectorType(type: unknown): type is Vector {\n return typeof type === 'string' && /^vector\\[\\d+\\]$/.test(type)\n}\n\nexport function isArrayType(type: unknown): type is ArraySearchableType {\n return typeof type === 'string' && IS_ARRAY_TYPE[type]\n}\n\nexport function getInnerType(type: ArraySearchableType): ScalarSearchableType {\n return INNER_TYPE[type]\n}\n\nexport function getVectorSize(type: string): number {\n const size = Number(type.slice(7, -1))\n\n switch (true) {\n case isNaN(size):\n throw createError('INVALID_VECTOR_VALUE', type)\n case size <= 0:\n throw createError('INVALID_VECTOR_SIZE', type)\n default:\n return size\n }\n}\n","import { AnyOrama } from '../types.js'\n\nexport type DocumentID = string | number\nexport type InternalDocumentID = number\n\nexport type InternalDocumentIDStore = {\n idToInternalId: Map<string, number>\n internalIdToId: string[]\n save: (store: InternalDocumentIDStore) => unknown\n load: <T extends AnyOrama>(orama: T, raw: unknown) => void\n}\n\nexport function createInternalDocumentIDStore(): InternalDocumentIDStore {\n return {\n idToInternalId: new Map(),\n internalIdToId: [],\n save,\n load\n }\n}\n\nexport function save(store: InternalDocumentIDStore): unknown {\n return {\n internalIdToId: store.internalIdToId\n }\n}\n\nexport function load<T extends AnyOrama>(orama: T, raw: unknown): void {\n const { internalIdToId } = raw as InternalDocumentIDStore\n\n orama.internalDocumentIDStore.idToInternalId.clear()\n orama.internalDocumentIDStore.internalIdToId = []\n const internalIdToIdLength = internalIdToId.length\n\n for (let i = 0; i < internalIdToIdLength; i++) {\n const internalIdItem = internalIdToId[i]\n orama.internalDocumentIDStore.idToInternalId.set(internalIdItem, i + 1)\n orama.internalDocumentIDStore.internalIdToId.push(internalIdItem)\n }\n}\n\nexport function getInternalDocumentId(store: InternalDocumentIDStore, id: DocumentID): InternalDocumentID {\n if (typeof id === 'string') {\n const internalId = store.idToInternalId.get(id)\n\n if (internalId) {\n return internalId\n }\n\n const currentId = store.idToInternalId.size + 1\n\n store.idToInternalId.set(id, currentId)\n store.internalIdToId.push(id)\n\n return currentId\n }\n\n if (id > store.internalIdToId.length) {\n return getInternalDocumentId(store, id.toString())\n }\n\n return id\n}\n\nexport function getDocumentIdFromInternalId(store: InternalDocumentIDStore, internalId: InternalDocumentID): string {\n if (store.internalIdToId.length < internalId) {\n throw new Error(`Invalid internalId ${internalId}`)\n }\n\n return store.internalIdToId[internalId - 1]\n}\n","import type {\n AnyIndexStore,\n AnyOrama,\n ArraySearchableType,\n BM25Params,\n ComparisonOperator,\n EnumArrComparisonOperator,\n EnumComparisonOperator,\n GeosearchOperation,\n GeosearchPolygonOperator,\n GeosearchRadiusOperator,\n IIndex,\n ScalarSearchableType,\n SearchableType,\n SearchableValue,\n Tokenizer,\n TokenScore,\n WhereCondition\n} from '../types.js'\nimport type { InsertOptions } from '../methods/insert.js'\nimport type { Point as BKDGeoPoint } from '../trees/bkd.js'\nimport { FindResult, RadixNode } from '../trees/radix.js'\nimport { createError } from '../errors.js'\nimport { AVLTree } from '../trees/avl.js'\nimport { FlatTree } from '../trees/flat.js'\nimport { RadixTree } from '../trees/radix.js'\nimport { BKDTree } from '../trees/bkd.js'\nimport { BoolNode } from '../trees/bool.js'\n\nimport { convertDistanceToMeters, setIntersection, setUnion } from '../utils.js'\nimport { BM25 } from './algorithms.js'\nimport { getInnerType, getVectorSize, isArrayType, isVectorType } from './defaults.js'\nimport {\n DocumentID,\n getInternalDocumentId,\n InternalDocumentID,\n InternalDocumentIDStore\n} from './internal-document-id-store.js'\nimport { VectorIndex, VectorType } from '../trees/vector.js'\n\nexport type FrequencyMap = {\n [property: string]: {\n [documentID: InternalDocumentID]:\n | {\n [token: string]: number\n }\n | undefined\n }\n}\n\nexport type TreeType = 'AVL' | 'Radix' | 'Bool' | 'Flat' | 'BKD'\n\nexport type TTree<T = TreeType, N = unknown> = {\n type: T\n node: N\n isArray: boolean\n}\n\nexport type Tree =\n | TTree<'Radix', RadixNode>\n | TTree<'AVL', AVLTree<number, InternalDocumentID>>\n | TTree<'Bool', BoolNode<InternalDocumentID>>\n | TTree<'Flat', FlatTree>\n | TTree<'BKD', BKDTree>\n\nexport interface Index extends AnyIndexStore {\n sharedInternalDocumentStore: InternalDocumentIDStore\n indexes: Record<string, Tree>\n // vectorIndexes: Record<string, TTree<'Vector', VectorIndex>>\n searchableProperties: string[]\n searchablePropertiesWithTypes: Record<string, SearchableType>\n frequencies: FrequencyMap\n tokenOccurrences: Record<string, Record<string, number>>\n avgFieldLength: Record<string, number>\n fieldLengths: Record<string, Record<InternalDocumentID, number | undefined>>\n}\n\nexport function insertDocumentScoreParameters(\n index: Index,\n prop: string,\n id: DocumentID,\n tokens: string[],\n docsCount: number\n): void {\n const internalId = getInternalDocumentId(index.sharedInternalDocumentStore, id)\n\n index.avgFieldLength[prop] = ((index.avgFieldLength[prop] ?? 0) * (docsCount - 1) + tokens.length) / docsCount\n index.fieldLengths[prop][internalId] = tokens.length\n index.frequencies[prop][internalId] = {}\n}\n\nexport function insertTokenScoreParameters(\n index: Index,\n prop: string,\n id: DocumentID,\n tokens: string[],\n token: string\n): void {\n let tokenFrequency = 0\n\n for (const t of tokens) {\n if (t === token) {\n tokenFrequency++\n }\n }\n\n const internalId = getInternalDocumentId(index.sharedInternalDocumentStore, id)\n const tf = tokenFrequency / tokens.length\n\n index.frequencies[prop][internalId]![token] = tf\n\n if (!(token in index.tokenOccurrences[prop])) {\n index.tokenOccurrences[prop][token] = 0\n }\n\n // increase a token counter that may not yet exist\n index.tokenOccurrences[prop][token] = (index.tokenOccurrences[prop][token] ?? 0) + 1\n}\n\nexport function removeDocumentScoreParameters(index: Index, prop: string, id: DocumentID, docsCount: number): void {\n const internalId = getInternalDocumentId(index.sharedInternalDocumentStore, id)\n\n if (docsCount > 1) {\n index.avgFieldLength[prop] =\n (index.avgFieldLength[prop] * docsCount - index.fieldLengths[prop][internalId]!) / (docsCount - 1)\n } else {\n index.avgFieldLength[prop] = undefined as unknown as number\n }\n index.fieldLengths[prop][internalId] = undefined\n index.frequencies[prop][internalId] = undefined\n}\n\nexport function removeTokenScoreParameters(index: Index, prop: string, token: string): void {\n index.tokenOccurrences[prop][token]--\n}\n\nexport function create<T extends AnyOrama, TSchema extends T['schema']>(\n orama: T,\n sharedInternalDocumentStore: T['internalDocumentIDStore'],\n schema: TSchema,\n index?: Index,\n prefix = ''\n): Index {\n if (!index) {\n index = {\n sharedInternalDocumentStore,\n indexes: {},\n vectorIndexes: {},\n searchableProperties: [],\n searchablePropertiesWithTypes: {},\n frequencies: {},\n tokenOccurrences: {},\n avgFieldLength: {},\n fieldLengths: {}\n }\n }\n\n for (const [prop, type] of Object.entries<SearchableType>(schema)) {\n const path = `${prefix}${prefix ? '.' : ''}${prop}`\n\n if (typeof type === 'object' && !Array.isArray(type)) {\n // Nested\n create(orama, sharedInternalDocumentStore, type, index, path)\n continue\n }\n\n if (isVectorType(type)) {\n index.searchableProperties.push(path)\n index.searchablePropertiesWithTypes[path] = type\n index.vectorIndexes[path] = {\n type: 'Vector',\n node: new VectorIndex(getVectorSize(type)),\n isArray: false,\n }\n } else {\n const isArray = /\\[/.test(type as string)\n switch (type) {\n case 'boolean':\n case 'boolean[]':\n index.indexes[path] = { type: 'Bool', node: new BoolNode(), isArray }\n break\n case 'number':\n case 'number[]':\n index.indexes[path] = { type: 'AVL', node: new AVLTree<number, InternalDocumentID>(0, []), isArray }\n break\n case 'string':\n case 'string[]':\n index.indexes[path] = { type: 'Radix', node: new RadixTree(), isArray }\n index.avgFieldLength[path] = 0\n index.frequencies[path] = {}\n index.tokenOccurrences[path] = {}\n index.fieldLengths[path] = {}\n break\n case 'enum':\n case 'enum[]':\n index.indexes[path] = { type: 'Flat', node: new FlatTree(), isArray }\n break\n case 'geopoint':\n index.indexes[path] = { type: 'BKD', node: new BKDTree(), isArray }\n break\n default:\n throw createError('INVALID_SCHEMA_TYPE', Array.isArray(type) ? 'array' : type, path)\n }\n\n index.searchableProperties.push(path)\n index.searchablePropertiesWithTypes[path] = type\n }\n }\n\n return index\n}\n\nfunction insertScalarBuilder(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n internalId: InternalDocumentID,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number,\n options?: InsertOptions\n) {\n return (value: SearchableValue) => {\n const { type, node } = index.indexes[prop]\n switch (type) {\n case 'Bool': {\n node[value ? 'true' : 'false'].add(internalId)\n break\n }\n case 'AVL': {\n const avlRebalanceThreshold = options?.avlRebalanceThreshold ?? 1\n node.insert(value as number, internalId, avlRebalanceThreshold)\n break\n }\n case 'Radix': {\n const tokens = tokenizer.tokenize(value as string, language, prop, false)\n implementation.insertDocumentScoreParameters(index, prop, internalId, tokens, docsCount)\n\n for (const token of tokens) {\n implementation.insertTokenScoreParameters(index, prop, internalId, tokens, token)\n\n node.insert(token, internalId)\n }\n\n break\n }\n case 'Flat': {\n node.insert(value as ScalarSearchableType, internalId)\n break\n }\n case 'BKD': {\n node.insert(value as unknown as BKDGeoPoint, [internalId])\n break\n }\n }\n }\n}\n\nexport function insert(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number,\n options?: InsertOptions\n): void {\n if (isVectorType(schemaType)) {\n return insertVector(index, prop, value as number[] | Float32Array, id, internalId)\n }\n\n const insertScalar = insertScalarBuilder(implementation, index, prop, internalId, language, tokenizer, docsCount, options)\n\n if (!isArrayType(schemaType)) {\n return insertScalar(value)\n }\n\n const elements = value as Array<string | number | boolean>\n const elementsLength = elements.length\n for (let i = 0; i < elementsLength; i++) {\n insertScalar(elements[i])\n }\n}\n\nexport function insertVector(index: AnyIndexStore, prop: string, value: number[] | VectorType, id: DocumentID, internalDocumentId: InternalDocumentID): void {\n index.vectorIndexes[prop].node.add(internalDocumentId, value)\n}\n\nfunction removeScalar(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: ScalarSearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n): boolean {\n if (isVectorType(schemaType)) {\n index.vectorIndexes[prop].node.remove(internalId)\n return true\n }\n\n const { type, node } = index.indexes[prop]\n switch (type) {\n case 'AVL': {\n node.removeDocument(value as number, internalId)\n return true\n }\n case 'Bool': {\n node[value ? 'true' : 'false'].delete(internalId)\n return true\n }\n case 'Radix': {\n const tokens = tokenizer.tokenize(value as string, language, prop)\n\n implementation.removeDocumentScoreParameters(index, prop, id, docsCount)\n\n for (const token of tokens) {\n implementation.removeTokenScoreParameters(index, prop, token)\n node.removeDocumentByWord(token, internalId)\n }\n\n return true\n }\n case 'Flat': {\n node.removeDocument(internalId, value as ScalarSearchableType)\n return true\n }\n case 'BKD': {\n node.removeDocByID(value as unknown as BKDGeoPoint, internalId)\n return false\n }\n }\n}\n\nexport function remove(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n): boolean {\n if (!isArrayType(schemaType)) {\n return removeScalar(\n implementation,\n index,\n prop,\n id,\n internalId,\n value,\n schemaType as ScalarSearchableType,\n language,\n tokenizer,\n docsCount\n )\n }\n\n const innerSchemaType = getInnerType(schemaType as ArraySearchableType)\n\n const elements = value as Array<string | number | boolean>\n const elementsLength = elements.length\n for (let i = 0; i < elementsLength; i++) {\n removeScalar(implementation, index, prop, id, internalId, elements[i], innerSchemaType, language, tokenizer, docsCount)\n }\n\n return true\n}\n\nexport function calculateResultScores(\n index: Index,\n prop: string,\n term: string,\n ids: InternalDocumentID[],\n docsCount: number,\n bm25Relevance: Required<BM25Params>,\n resultsMap: Map<number, number>,\n boostPerProperty: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined\n) {\n const documentIDs = Array.from(ids)\n\n // Exact fields for TF-IDF\n const avgFieldLength = index.avgFieldLength[prop]\n const fieldLengths = index.fieldLengths[prop]\n const oramaOccurrences = index.tokenOccurrences[prop]\n const oramaFrequencies = index.frequencies[prop]\n\n // oramaOccurrences[term] can be undefined, 0, string, or { [k: string]: number }\n const termOccurrences = typeof oramaOccurrences[term] === 'number' ? oramaOccurrences[term] ?? 0 : 0\n\n // Calculate TF-IDF value for each term, in each document, for each index.\n const documentIDsLength = documentIDs.length\n for (let k = 0; k < documentIDsLength; k++) {\n const internalId = documentIDs[k]\n if (whereFiltersIDs && !whereFiltersIDs.has(internalId)) {\n continue\n }\n\n const tf = oramaFrequencies?.[internalId]?.[term] ?? 0\n\n const bm25 = BM25(\n tf,\n termOccurrences,\n docsCount,\n fieldLengths[internalId]!,\n avgFieldLength,\n bm25Relevance,\n )\n\n if (resultsMap.has(internalId)) {\n resultsMap.set(internalId, resultsMap.get(internalId)! + bm25 * boostPerProperty)\n } else {\n resultsMap.set(internalId, bm25 * boostPerProperty)\n }\n }\n}\n\nfunction searchInProperty(\n index: Index,\n tree: RadixTree,\n prop: string,\n tokens: string[],\n exact: boolean,\n tolerance: number,\n resultsMap: Map<number, number>,\n boostPerProperty: number,\n bm25Relevance: Required<BM25Params>,\n docsCount: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined\n) {\n const tokenLength = tokens.length;\n for (let i = 0; i < tokenLength; i++) {\n const term = tokens[i];\n\n const searchResult = tree.find({ term, exact, tolerance })\n\n const termsFound = Object.keys(searchResult)\n const termsFoundLength = termsFound.length;\n for (let j = 0; j < termsFoundLength; j++) {\n const word = termsFound[j]\n const ids = searchResult[word]\n calculateResultScores(\n index,\n prop,\n word,\n ids,\n docsCount,\n bm25Relevance,\n resultsMap,\n boostPerProperty,\n whereFiltersIDs,\n )\n }\n }\n}\n\nexport function search(\n index: Index,\n term: string,\n tokenizer: Tokenizer,\n language: string | undefined,\n propertiesToSearch: string[],\n exact: boolean,\n tolerance: number,\n boost: Record<string, number>,\n relevance: Required<BM25Params>,\n docsCount: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined,\n): TokenScore[] {\n const tokens = tokenizer.tokenize(term, language)\n\n const resultsMap = new Map<number, number>()\n for (const prop of propertiesToSearch) {\n if (!(prop in index.indexes)) {\n continue\n }\n\n const tree = index.indexes[prop]\n const { type } = tree\n if (type !== 'Radix') {\n throw createError('WRONG_SEARCH_PROPERTY_TYPE', prop)\n }\n const boostPerProperty = boost[prop] ?? 1\n if (boostPerProperty <= 0) {\n throw createError('INVALID_BOOST_VALUE', boostPerProperty)\n }\n\n // if the tokenizer returns an empty array, we returns all the documents\n if (tokens.length === 0 && !term) {\n tokens.push('')\n }\n\n searchInProperty(\n index,\n tree.node,\n prop,\n tokens,\n exact,\n tolerance,\n resultsMap,\n boostPerProperty,\n relevance,\n docsCount,\n whereFiltersIDs,\n )\n }\n\n return Array.from(resultsMap)\n}\n\nexport function searchByWhereClause<T extends AnyOrama>(\n index: Index,\n tokenizer: Tokenizer,\n filters: Partial<WhereCondition<T['schema']>>,\n language: string | undefined\n): Set<InternalDocumentID> {\n const filterKeys = Object.keys(filters)\n\n const filtersMap: Record<string, Set<InternalDocumentID>> = filterKeys.reduce(\n (acc, key) => ({\n [key]: new Set(),\n ...acc\n }),\n {}\n )\n\n for (const param of filterKeys) {\n const operation = filters[param]!\n\n if (typeof index.indexes[param] === 'undefined') {\n throw createError('UNKNOWN_FILTER_PROPERTY', param)\n }\n\n const { node, type, isArray } = index.indexes[param]\n\n if (type === 'Bool') {\n const idx = node\n const filteredIDs = operation ? idx.true : idx.false\n filtersMap[param] = setUnion(filtersMap[param], filteredIDs)\n continue\n }\n\n if (type === 'BKD') {\n let reqOperation: 'radius' | 'polygon'\n\n if ('radius' in (operation as GeosearchOperation)) {\n reqOperation = 'radius'\n } else if ('polygon' in (operation as GeosearchOperation)) {\n reqOperation = 'polygon'\n } else {\n throw new Error(`Invalid operation ${operation}`)\n }\n\n if (reqOperation === 'radius') {\n const {\n value,\n coordinates,\n unit = 'm',\n inside = true,\n highPrecision = false\n } = operation[reqOperation] as GeosearchRadiusOperator['radius']\n const distanceInMeters = convertDistanceToMeters(value, unit)\n const ids = node.searchByRadius(coordinates as BKDGeoPoint, distanceInMeters, inside, undefined, highPrecision)\n filtersMap[param] = addGeoResult(filtersMap[param], ids)\n } else {\n const {\n coordinates,\n inside = true,\n highPrecision = false\n } = operation[reqOperation] as GeosearchPolygonOperator['polygon']\n const ids = node.searchByPolygon(coordinates as BKDGeoPoint[], inside, undefined, highPrecision)\n filtersMap[param] = addGeoResult(filtersMap[param], ids)\n }\n\n continue\n }\n\n if (type === 'Radix' && (typeof operation === 'string' || Array.isArray(operation))) {\n for (const raw of [operation].flat()) {\n const term = tokenizer.tokenize(raw, language, param)\n for (const t of term) {\n const filteredIDsResults = node.find({ term: t, exact: true })\n filtersMap[param] = addFindResult(filtersMap[param], filteredIDsResults)\n }\n }\n\n continue\n }\n\n const operationKeys = Object.keys(operation)\n\n if (operationKeys.length > 1) {\n throw createError('INVALID_FILTER_OPERATION', operationKeys.length)\n }\n\n if (type === 'Flat') {\n const results = new Set(isArray\n ? node.filterArr(operation as EnumArrComparisonOperator)\n : node.filter(operation as EnumComparisonOperator))\n\n filtersMap[param] = setUnion(filtersMap[param], results)\n\n continue\n }\n\n if (type === 'AVL') {\n const operationOpt = operationKeys[0] as keyof ComparisonOperator\n const operationValue = (operation as ComparisonOperator)[operationOpt]\n let filteredIDs: Set<InternalDocumentID> \n\n switch (operationOpt) {\n case 'gt': {\n filteredIDs = node.greaterThan(operationValue as number, false)\n break\n }\n case 'gte': {\n filteredIDs = node.greaterThan(operationValue as number, true)\n break\n }\n case 'lt': {\n filteredIDs = node.lessThan(operationValue as number, false)\n break\n }\n case 'lte': {\n filteredIDs = node.lessThan(operationValue as number, true)\n break\n }\n case 'eq': {\n const ret = node.find(operationValue as number)\n filteredIDs = ret ?? new Set()\n break\n }\n case 'between': {\n const [min, max] = operationValue as number[]\n filteredIDs = node.rangeSearch(min, max)\n break\n }\n default:\n throw createError('INVALID_FILTER_OPERATION', operationOpt)\n }\n\n filtersMap[param] = setUnion(filtersMap[param], filteredIDs)\n }\n }\n\n // AND operation: calculate the intersection between all the IDs in filterMap\n return setIntersection(...Object.values(filtersMap))\n}\n\nexport function getSearchableProperties(index: Index): string[] {\n return index.searchableProperties\n}\n\nexport function getSearchablePropertiesWithTypes(index: Index): Record<string, SearchableType> {\n return index.searchablePropertiesWithTypes\n}\n\nexport function load<R = unknown>(sharedInternalDocumentStore: InternalDocumentIDStore, raw: R): Index {\n const {\n indexes: rawIndexes,\n vectorIndexes: rawVectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n } = raw as Index\n\n const indexes: Index['indexes'] = {}\n const vectorIndexes: Index['vectorIndexes'] = {}\n\n for (const prop of Object.keys(rawIndexes)) {\n const { node, type, isArray } = rawIndexes[prop]\n\n switch (type) {\n case 'Radix':\n indexes[prop] = {\n type: 'Radix',\n node: RadixTree.fromJSON(node),\n isArray\n }\n break\n case 'Flat':\n indexes[prop] = {\n type: 'Flat',\n node: FlatTree.fromJSON(node),\n isArray\n }\n break\n case 'AVL':\n indexes[prop] = {\n type: 'AVL',\n node: AVLTree.fromJSON(node),\n isArray\n }\n break\n case 'BKD':\n indexes[prop] = {\n type: 'BKD',\n node: BKDTree.fromJSON(node),\n isArray\n }\n break\n case 'Bool':\n indexes[prop] = {\n type: 'Bool',\n node: BoolNode.fromJSON(node),\n isArray\n }\n break\n default:\n indexes[prop] = rawIndexes[prop]\n }\n }\n\n for (const idx of Object.keys(rawVectorIndexes)) {\n vectorIndexes[idx] = {\n type: 'Vector',\n isArray: false,\n node: VectorIndex.fromJSON(rawVectorIndexes[idx])\n }\n }\n\n return {\n sharedInternalDocumentStore,\n indexes,\n vectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n }\n}\n\nexport function save<R = unknown>(index: Index): R {\n const {\n indexes,\n vectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n } = index\n\n const dumpVectorIndexes: Record<string, unknown> = {}\n for (const idx of Object.keys(vectorIndexes)) {\n dumpVectorIndexes[idx] = vectorIndexes[idx].node.toJSON()\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const savedIndexes: any = {}\n for (const name of Object.keys(indexes)) {\n const { type, node, isArray } = indexes[name]\n if (type === 'Flat'\n || type === 'Radix'\n || type === 'AVL'\n || type === 'BKD'\n || type === 'Bool'\n ) {\n savedIndexes[name] = {\n type,\n node: node.toJSON(),\n isArray\n }\n } else {\n savedIndexes[name] = indexes[name]\n savedIndexes[name].node = savedIndexes[name].node.toJSON()\n }\n }\n\n return {\n indexes: savedIndexes,\n vectorIndexes: dumpVectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n } as R\n}\n\nexport function createIndex(): IIndex<Index> {\n return {\n create,\n insert,\n remove,\n insertDocumentScoreParameters,\n insertTokenScoreParameters,\n removeDocumentScoreParameters,\n removeTokenScoreParameters,\n calculateResultScores,\n search,\n searchByWhereClause,\n getSearchableProperties,\n getSearchablePropertiesWithTypes,\n load,\n save\n }\n}\n\nfunction addGeoResult(set: Set<InternalDocumentID> | undefined, ids: Array<{ docIDs: InternalDocumentID[] }>): Set<InternalDocumentID> {\n if (!set) {\n set = new Set()\n }\n\n const idsLength = ids.length\n for (let i = 0; i < idsLength; i++) {\n const entry = ids[i].docIDs\n const idsLength = entry.length\n for (let j = 0; j < idsLength; j++) {\n set.add(entry[j])\n }\n }\n\n return set\n}\n\nfunction addFindResult(set: Set<InternalDocumentID> | undefined, filteredIDsResults: FindResult): Set<InternalDocumentID> {\n if (!set) {\n set = new Set()\n }\n\n const keys = Object.keys(filteredIDsResults)\n const keysLength = keys.length\n for (let i = 0; i < keysLength; i++) {\n const ids = filteredIDsResults[keys[i]]\n const idsLength = ids.length\n for (let j = 0; j < idsLength; j++) {\n set.add(ids[j])\n }\n }\n\n return set\n}\n","/* eslint-disable no-extra-semi */\n/* eslint-disable @typescript-eslint/no-this-alias */\nimport { Nullable } from '../types.js'\nimport { setUnion } from '../utils.js'\n\nexport class AVLNode<K, V> {\n public k: K\n public v: Set<V>\n public l: Nullable<AVLNode<K, V>> = null\n public r: Nullable<AVLNode<K, V>> = null\n public h: number = 1\n\n constructor(key: K, value: V[]) {\n this.k = key\n this.v = new Set(value)\n }\n\n public updateHeight(): void {\n this.h = Math.max(AVLNode.getHeight(this.l), AVLNode.getHeight(this.r)) + 1\n }\n\n public static getHeight<K, V>(node: Nullable<AVLNode<K, V>>): number {\n return node ? node.h : 0\n }\n\n public getBalanceFactor(): number {\n return AVLNode.getHeight(this.l) - AVLNode.getHeight(this.r)\n }\n\n public rotateLeft(): AVLNode<K, V> {\n const newRoot = this.r as AVLNode<K, V>\n this.r = newRoot.l\n newRoot.l = this\n this.updateHeight()\n newRoot.updateHeight()\n return newRoot\n }\n\n public rotateRight(): AVLNode<K, V> {\n const newRoot = this.l as AVLNode<K, V>\n this.l = newRoot.r\n newRoot.r = this\n this.updateHeight()\n newRoot.updateHeight()\n return newRoot\n }\n\n public toJSON(): object {\n return {\n k: this.k,\n v: Array.from(this.v),\n l: this.l ? this.l.toJSON() : null,\n r: this.r ? this.r.toJSON() : null,\n h: this.h\n }\n }\n\n public static fromJSON<K, V>(json: any): AVLNode<K, V> {\n const node = new AVLNode<K, V>(json.k, json.v)\n node.l = json.l ? AVLNode.fromJSON<K, V>(json.l) : null\n node.r = json.r ? AVLNode.fromJSON<K, V>(json.r) : null\n node.h = json.h\n return node\n }\n}\n\nexport class AVLTree<K, V> {\n public root: Nullable<AVLNode<K, V>> = null\n private insertCount = 0\n\n constructor(key?: K, value?: V[]) {\n if (key !== undefined && value !== undefined) {\n this.root = new AVLNode(key, value)\n }\n }\n\n public insert(key: K, value: V, rebalanceThreshold = 1000): void {\n this.root = this.insertNode(this.root, key, value, rebalanceThreshold)\n }\n\n public insertMultiple(key: K, value: V[], rebalanceThreshold = 1000): void {\n for (const v of value) {\n this.insert(key, v, rebalanceThreshold)\n }\n }\n\n // Rebalance the tree if the insert count reaches the threshold.\n // This will improve insertion performance since we won't be rebalancing the tree on every insert.\n // When inserting docs using `insertMultiple`, the threshold will be set to the number of docs being inserted.\n // We can force rebalancing the tree by setting the threshold to 1 (default).\n public rebalance() {\n if (this.root) {\n this.root = this.rebalanceNode(this.root!)\n }\n }\n\n public toJSON(): object {\n return {\n root: this.root ? this.root.toJSON() : null,\n insertCount: this.insertCount\n }\n }\n\n public static fromJSON<K, V>(json: any): AVLTree<K, V> {\n const tree = new AVLTree<K, V>()\n tree.root = json.root ? AVLNode.fromJSON<K, V>(json.root) : null\n tree.insertCount = json.insertCount || 0\n return tree\n }\n\n private insertNode(node: Nullable<AVLNode<K, V>>, key: K, value: V, rebalanceThreshold: number): AVLNode<K, V> {\n if (node === null) {\n return new AVLNode(key, [value])\n }\n\n const path: Array<{ parent: Nullable<AVLNode<K, V>>; node: AVLNode<K, V> }> = []\n let current = node\n let parent: Nullable<AVLNode<K, V>> = null\n\n while (current !== null) {\n path.push({ parent, node: current })\n\n if (key < current.k) {\n if (current.l === null) {\n current.l = new AVLNode(key, [value])\n path.push({ parent: current, node: current.l })\n break\n } else {\n parent = current\n current = current.l\n }\n } else if (key > current.k) {\n if (current.r === null) {\n current.r = new AVLNode(key, [value])\n path.push({ parent: current, node: current.r })\n break\n } else {\n parent = current\n current = current.r\n }\n } else {\n // Key already exists\n current.v.add(value)\n /*\n if (Array.isArray(current.v)) {\n if (Array.isArray(value)) {\n ;(current.v as any[]).push(...(value as V[]))\n } else {\n ;(current.v as any[]).push(value)\n }\n } else {\n current.v = new Set([value])\n }\n */\n return node\n }\n }\n\n // Update heights and rebalance if necessary\n let needRebalance = false\n if (this.insertCount++ % rebalanceThreshold === 0) {\n needRebalance = true\n }\n\n for (let i = path.length - 1; i >= 0; i--) {\n const { parent, node: currentNode } = path[i]\n currentNode.updateHeight()\n\n if (needRebalance) {\n const rebalancedNode = this.rebalanceNode(currentNode)\n if (parent) {\n if (parent.l === currentNode) {\n parent.l = rebalancedNode\n } else if (parent.r === currentNode) {\n parent.r = rebalancedNode\n }\n } else {\n // This is the root node\n node = rebalancedNode\n }\n }\n }\n\n return node\n }\n\n private rebalanceNode(node: AVLNode<K, V>): AVLNode<K, V> {\n const balanceFactor = node.getBalanceFactor()\n\n if (balanceFactor > 1) {\n // Left heavy\n if (node.l && node.l.getBalanceFactor() >= 0) {\n // Left Left Case\n return node.rotateRight()\n } else if (node.l) {\n // Left Right Case\n node.l = node.l.rotateLeft()\n return node.rotateRight()\n }\n }\n\n if (balanceFactor < -1) {\n // Right heavy\n if (node.r && node.r.getBalanceFactor() <= 0) {\n // Right Right Case\n return node.rotateLeft()\n } else if (node.r) {\n // Right Left Case\n node.r = node.r.rotateRight()\n return node.rotateLeft()\n }\n }\n\n return node\n }\n\n public find(key: K): Nullable<Set<V>> {\n const node = this.findNodeByKey(key)\n return node ? node.v : null\n }\n\n public contains(key: K): boolean {\n return this.find(key) !== null\n }\n\n public getSize(): number {\n let count = 0\n const stack: Array<Nullable<AVLNode<K, V>>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.l\n }\n current = stack.pop()!\n count++\n current = current.r\n }\n\n return count\n }\n\n public isBalanced(): boolean {\n if (!this.root) return true\n\n const stack: Array<AVLNode<K, V>> = [this.root]\n\n while (stack.length > 0) {\n const node = stack.pop()!\n const balanceFactor = node.getBalanceFactor()\n if (Math.abs(balanceFactor) > 1) {\n return false\n }\n\n if (node.l) stack.push(node.l)\n if (node.r) stack.push(node.r)\n }\n\n return true\n }\n\n public remove(key: K): void {\n this.root = this.removeNode(this.root, key)\n }\n\n public removeDocument(key: K, id: V) {\n const node = this.findNodeByKey(key)\n\n if (!node) {\n return\n }\n\n if (node.v.size === 1) {\n this.root = this.removeNode(this.root, key)\n } else {\n node.v = new Set([...node.v.values()].filter((v) => v !== id))\n }\n }\n\n private findNodeByKey(key: K): Nullable<AVLNode<K, V>> {\n let node = this.root\n while (node) {\n if (key < node.k) {\n node = node.l\n } else if (key > node.k) {\n node = node.r\n } else {\n return node\n }\n }\n return null\n }\n\n private removeNode(node: Nullable<AVLNode<K, V>>, key: K): Nullable<AVLNode<K, V>> {\n if (node === null) return null\n\n const path: Array<AVLNode<K, V>> = []\n let current = node\n\n while (current !== null && current.k !== key) {\n path.push(current)\n if (key < current.k) {\n current = current.l!\n } else {\n current = current.r!\n }\n }\n\n if (current === null) {\n // Key not found\n return node\n }\n\n // Node with only one child or no child\n if (current.l === null || current.r === null) {\n const child = current.l ? current.l : current.r\n\n if (path.length === 0) {\n // Node to be deleted is root\n node = child\n } else {\n const parent = path[path.length - 1]\n if (parent.l === current) {\n parent.l = child\n } else {\n parent.r = child\n }\n }\n } else {\n // Node with two children: Get the inorder successor\n let successorParent = current\n let successor = current.r\n\n while (successor.l !== null) {\n successorParent = successor\n successor = successor.l\n }\n\n // Copy the successor's content to current node\n current.k = successor.k\n current.v = successor.v\n\n // Delete the successor\n if (successorParent.l === successor) {\n successorParent.l = successor.r\n } else {\n successorParent.r = successor.r\n }\n\n current = successorParent\n }\n\n // Update heights and rebalance\n path.push(current)\n for (let i = path.length - 1; i >= 0; i--) {\n const currentNode = path[i]\n currentNode.updateHeight()\n const rebalancedNode = this.rebalanceNode(currentNode)\n if (i > 0) {\n const parent = path[i - 1]\n if (parent.l === currentNode) {\n parent.l = rebalancedNode\n } else if (parent.r === currentNode) {\n parent.r = rebalancedNode\n }\n } else {\n // Root node\n node = rebalancedNode\n }\n }\n\n return node\n }\n\n public rangeSearch(min: K, max: K): Set<V> {\n let result: Set<V> = new Set()\n const stack: Array<AVLNode<K, V>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.l\n }\n current = stack.pop()!\n if (current.k >= min && current.k <= max) {\n result = setUnion(result, current.v)\n }\n if (current.k > max) {\n break\n }\n current = current.r\n }\n\n return result\n }\n\n public greaterThan(key: K, inclusive = false): Set<V> {\n let result: Set<V> = new Set()\n const stack: Array<AVLNode<K, V>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.r // Traverse right subtree first\n }\n current = stack.pop()!\n if ((inclusive && current.k >= key) || (!inclusive && current.k > key)) {\n result = setUnion(result, current.v)\n } else if (current.k <= key) {\n break // Since we're traversing in descending order, we can break early\n }\n current = current.l\n }\n\n return result\n }\n\n public lessThan(key: K, inclusive = false): Set<V> {\n let result: Set<V> = new Set()\n const stack: Array<AVLNode<K, V>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.l\n }\n current = stack.pop()!\n if ((inclusive && current.k <= key) || (!inclusive && current.k < key)) {\n result = setUnion(result, current.v)\n } else if (current.k > key) {\n break // Since we're traversing in ascending order, we can break early\n }\n current = current.r\n }\n\n return result\n }\n}\n","import { InternalDocumentID } from '../components/internal-document-id-store.js'\nimport { EnumArrComparisonOperator, EnumComparisonOperator, Nullable, ScalarSearchableValue } from '../types.js'\n\nexport class FlatTree {\n numberToDocumentId: Map<ScalarSearchableValue, Set<InternalDocumentID>>\n\n constructor() {\n this.numberToDocumentId = new Map()\n }\n\n insert(key: ScalarSearchableValue, value: InternalDocumentID): void {\n if (this.numberToDocumentId.has(key)) {\n this.numberToDocumentId.get(key)!.add(value)\n } else {\n this.numberToDocumentId.set(key, new Set([value]))\n }\n }\n\n find(key: ScalarSearchableValue): Nullable<InternalDocumentID[]> {\n const idSet = this.numberToDocumentId.get(key)\n return idSet ? Array.from(idSet) : null\n }\n\n remove(key: ScalarSearchableValue): void {\n this.numberToDocumentId.delete(key)\n }\n\n removeDocument(id: InternalDocumentID, key: ScalarSearchableValue): void {\n const idSet = this.numberToDocumentId.get(key)\n if (idSet) {\n idSet.delete(id)\n if (idSet.size === 0) {\n this.numberToDocumentId.delete(key)\n }\n }\n }\n\n contains(key: ScalarSearchableValue): boolean {\n return this.numberToDocumentId.has(key)\n }\n\n getSize(): number {\n let size = 0\n for (const idSet of this.numberToDocumentId.values()) {\n size += idSet.size\n }\n return size\n }\n\n filter(operation: EnumComparisonOperator): InternalDocumentID[] {\n const operationKeys = Object.keys(operation)\n\n if (operationKeys.length !== 1) {\n throw new Error('Invalid operation')\n }\n\n const operationType = operationKeys[0] as keyof EnumComparisonOperator\n\n switch (operationType) {\n case 'eq': {\n const value = operation[operationType]!\n const idSet = this.numberToDocumentId.get(value)\n return idSet ? Array.from(idSet) : []\n }\n case 'in': {\n const values = operation[operationType]!\n const resultSet: Set<InternalDocumentID> = new Set()\n for (const value of values) {\n const idSet = this.numberToDocumentId.get(value)\n if (idSet) {\n for (const id of idSet) {\n resultSet.add(id)\n }\n }\n }\n return Array.from(resultSet)\n }\n case 'nin': {\n const excludeValues = new Set<ScalarSearchableValue>(operation[operationType]!)\n const resultSet: Set<InternalDocumentID> = new Set()\n for (const [key, idSet] of this.numberToDocumentId.entries()) {\n if (!excludeValues.has(key)) {\n for (const id of idSet) {\n resultSet.add(id)\n }\n }\n }\n return Array.from(resultSet)\n }\n default:\n throw new Error('Invalid operation')\n }\n }\n\n filterArr(operation: EnumArrComparisonOperator): InternalDocumentID[] {\n const operationKeys = Object.keys(operation)\n\n if (operationKeys.length !== 1) {\n throw new Error('Invalid operation')\n }\n\n const operationType = operationKeys[0] as keyof EnumArrComparisonOperator\n\n switch (operationType) {\n case 'containsAll': {\n const values = operation[operationType]!\n const idSets = values.map((value) => this.numberToDocumentId.get(value) ?? new Set())\n if (idSets.length === 0) return []\n const intersection = idSets.reduce((prev, curr) => {\n return new Set([...prev].filter((id) => curr.has(id)))\n })\n return Array.from(intersection) as InternalDocumentID[]\n }\n default:\n throw new Error('Invalid operation')\n }\n }\n\n static fromJSON(json: any): FlatTree {\n if (!json.numberToDocumentId) {\n throw new Error('Invalid Flat Tree JSON')\n }\n\n const tree = new FlatTree()\n for (const [key, ids] of json.numberToDocumentId) {\n tree.numberToDocumentId.set(key, new Set(ids))\n }\n return tree\n }\n\n toJSON(): any {\n return {\n numberToDocumentId: Array.from(this.numberToDocumentId.entries()).map(([key, idSet]) => [key, Array.from(idSet)])\n }\n }\n}\n","export type BoundedMetric = {\n isBounded: boolean\n distance: number\n}\n\n/**\n * Inspired by:\n * https://github.com/Yomguithereal/talisman/blob/86ae55cbd040ff021d05e282e0e6c71f2dde21f8/src/metrics/levenshtein.js#L218-L340\n */\nfunction _boundedLevenshtein(term: string, word: string, tolerance: number): number {\n // Handle base cases\n if (tolerance < 0) return -1\n if (term === word) return 0\n\n const m = term.length\n const n = word.length\n\n // Special case for empty strings\n if (m === 0) return n <= tolerance ? n : -1\n if (n === 0) return m <= tolerance ? m : -1\n\n // term = term.toLowerCase()\n // word = word.toLowerCase()\n\n const diff = Math.abs(m - n)\n // Special case for prefixes\n // If the searching word starts with the indexed word, return early.\n if (term.startsWith(word)) {\n // We just check if the remaining characters are within the tolerance\n return diff <= tolerance ? diff : -1\n }\n // If the indexed word starts with the searching word, return early.\n if (word.startsWith(term)) {\n // any prefixed word is within the tolerance\n return 0\n }\n\n // If the length difference is greater than the tolerance, return early\n if (diff > tolerance) return -1\n\n // Initialize the matrix\n const matrix: number[][] = []\n for (let i = 0; i <= m; i++) {\n matrix[i] = [i]\n for (let j = 1; j <= n; j++) {\n matrix[i][j] = i === 0 ? j : 0\n }\n }\n\n // Fill the matrix\n for (let i = 1; i <= m; i++) {\n let rowMin = Infinity\n for (let j = 1; j <= n; j++) {\n if (term[i - 1] === word[j - 1]) {\n matrix[i][j] = matrix[i - 1][j - 1]\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j] + 1, // deletion\n matrix[i][j - 1] + 1, // insertion\n matrix[i - 1][j - 1] + 1 // substitution\n )\n }\n rowMin = Math.min(rowMin, matrix[i][j])\n }\n\n // Early termination if all values in this row exceed tolerance\n if (rowMin > tolerance) {\n return -1\n }\n }\n\n return matrix[m][n] <= tolerance ? matrix[m][n] : -1\n}\n\n/**\n * Computes the Levenshtein distance between two strings (a, b), returning early with -1 if the distance\n * is greater than the given tolerance.\n * It assumes that:\n * - tolerance >= ||a| - |b|| >= 0\n */\nexport function boundedLevenshtein(term: string, w: string, tolerance: number): BoundedMetric {\n const distance = _boundedLevenshtein(term, w, tolerance)\n return {\n distance,\n isBounded: distance >= 0\n }\n}\n\n// This is only used internally, keep in sync with the previous one\nexport function syncBoundedLevenshtein(term: string, w: string, tolerance: number): BoundedMetric {\n const distance = _boundedLevenshtein(term, w, tolerance)\n return {\n distance,\n isBounded: distance >= 0\n }\n}\n\nexport function levenshtein(a: string, b: string): number {\n /* c8 ignore next 3 */\n if (!a.length) {\n return b.length\n }\n\n /* c8 ignore next 3 */\n if (!b.length) {\n return a.length\n }\n\n const swap = a\n if (a.length > b.length) {\n a = b\n b = swap\n }\n\n const row = Array.from({ length: a.length + 1 }, (_, i) => i)\n let val = 0\n\n for (let i = 1; i <= b.length; i++) {\n let prev = i\n\n for (let j = 1; j <= a.length; j++) {\n if (b[i - 1] === a[j - 1]) {\n val = row[j - 1]\n } else {\n val = Math.min(row[j - 1] + 1, Math.min(prev + 1, row[j] + 1))\n }\n\n row[j - 1] = prev\n prev = val\n }\n row[a.length] = prev\n }\n\n return row[a.length]\n}\n","/* eslint-disable @typescript-eslint/no-this-alias */\nimport { syncBoundedLevenshtein } from '../components/levenshtein.js'\nimport { InternalDocumentID } from '../components/internal-document-id-store.js'\nimport { getOwnProperty } from '../utils.js'\n\ninterface FindParams {\n term: string\n exact?: boolean\n tolerance?: number\n}\n\nexport type FindResult = Record<string, InternalDocumentID[]>\n\nexport class RadixNode {\n // Node key\n public k: string\n // Node subword\n public s: string\n // Node children\n public c: Map<string, RadixNode> = new Map()\n // Node documents\n public d: Set<InternalDocumentID> = new Set()\n // Node end\n public e: boolean\n // Node word\n public w = ''\n\n constructor(key: string, subWord: string, end: boolean) {\n this.k = key\n this.s = subWord\n this.e = end\n }\n\n public updateParent(parent: RadixNode): void {\n this.w = parent.w + this.s\n }\n\n public addDocument(docID: InternalDocumentID): void {\n this.d.add(docID)\n }\n\n public removeDocument(docID: InternalDocumentID): boolean {\n return this.d.delete(docID)\n }\n\n public findAllWords(output: FindResult, term: string, exact?: boolean, tolerance?: number): FindResult {\n const stack: RadixNode[] = [this]\n while (stack.length > 0) {\n const node = stack.pop()!\n \n if (node.e) {\n const { w, d: docIDs } = node\n \n if (exact && w !== term) {\n continue\n }\n\n // check if _output[w] exists and then add the doc to it\n // always check in own property to prevent access to inherited properties\n // fix https://github.com/askorama/orama/issues/137\n if (getOwnProperty(output, w) !== null) {\n if (tolerance) {\n const difference = Math.abs(term.length - w.length)\n \n if (difference <= tolerance && syncBoundedLevenshtein(term, w, tolerance).isBounded) {\n output[w] = []\n } else {\n continue\n }\n } else {\n output[w] = []\n }\n } \n\n // check if _output[w] exists and then add the doc to it\n // always check in own property to prevent access to inherited properties\n // fix https://github.com/askorama/orama/issues/137\n if (getOwnProperty(output, w) != null && docIDs.size > 0) {\n const docs = output[w]\n for (const docID of docIDs) {\n if (!docs.includes(docID)) {\n docs.push(docID)\n }\n }\n }\n }\n \n if (node.c.size > 0) {\n stack.push(...node.c.values())\n }\n }\n return output\n } \n\n public insert(word: string, docId: InternalDocumentID): void {\n let node: RadixNode = this\n let i = 0\n const wordLength = word.length\n \n while (i < wordLength) {\n const currentCharacter = word[i]\n const childNode = node.c.get(currentCharacter)\n \n if (childNode) {\n const edgeLabel = childNode.s\n const edgeLabelLength = edgeLabel.length\n let j = 0\n \n // Find the common prefix length between edgeLabel and the remaining word\n while (j < edgeLabelLength && i + j < wordLength && edgeLabel[j] === word[i + j]) {\n j++\n }\n \n if (j === edgeLabelLength) {\n // Edge label fully matches; proceed to the child node\n node = childNode\n i += j\n if (i === wordLength) {\n // The word is a prefix of an existing word\n if (!childNode.e) {\n childNode.e = true\n }\n childNode.addDocument(docId)\n return\n }\n continue\n }\n \n // Split the edgeLabel at the common prefix\n const commonPrefix = edgeLabel.slice(0, j)\n const newEdgeLabel = edgeLabel.slice(j)\n const newWordLabel = word.slice(i + j)\n \n // Create an intermediate node for the common prefix\n const inbetweenNode = new RadixNode(commonPrefix[0], commonPrefix, false)\n node.c.set(commonPrefix[0], inbetweenNode)\n inbetweenNode.updateParent(node)\n \n // Update the existing childNode\n childNode.s = newEdgeLabel\n childNode.k = newEdgeLabel[0]\n inbetweenNode.c.set(newEdgeLabel[0], childNode)\n childNode.updateParent(inbetweenNode)\n \n if (newWordLabel) {\n // Create a new node for the remaining part of the word\n const newNode = new RadixNode(newWordLabel[0], newWordLabel, true)\n newNode.addDocument(docId)\n inbetweenNode.c.set(newWordLabel[0], newNode)\n newNode.updateParent(inbetweenNode)\n } else {\n // The word ends at the inbetweenNode\n inbetweenNode.e = true\n inbetweenNode.addDocument(docId)\n }\n return\n } else {\n // No matching child; create a new node\n const newNode = new RadixNode(currentCharacter, word.slice(i), true)\n newNode.addDocument(docId)\n node.c.set(currentCharacter, newNode)\n newNode.updateParent(node)\n return\n }\n }\n \n // If we reach here, the word already exists in the tree\n if (!node.e) {\n node.e = true\n }\n node.addDocument(docId)\n } \n\n private _findLevenshtein(\n term: string,\n index: number,\n tolerance: number,\n originalTolerance: number,\n output: FindResult\n ) {\n const stack: Array<{ node: RadixNode; index: number; tolerance: number }> = [{ node: this, index, tolerance }]\n\n while (stack.length > 0) {\n const { node, index, tolerance } = stack.pop()!\n\n if (node.w.startsWith(term)) {\n node.findAllWords(output, term, false, 0)\n continue\n }\n\n if (tolerance < 0) {\n continue\n }\n\n if (node.e) {\n const { w, d: docIDs } = node\n if (w) {\n if (syncBoundedLevenshtein(term, w, originalTolerance).isBounded) {\n output[w] = []\n }\n if (getOwnProperty(output, w) !== undefined && docIDs.size > 0) {\n const docs = new Set(output[w])\n\n for (const docID of docIDs) {\n docs.add(docID)\n }\n output[w] = Array.from(docs)\n }\n }\n }\n\n if (index >= term.length) {\n continue\n }\n\n const currentChar = term[index]\n\n // 1. If node has child matching term[index], push { node: childNode, index +1, tolerance }\n if (node.c.has(currentChar)) {\n const childNode = node.c.get(currentChar)!\n stack.push({ node: childNode, index: index + 1, tolerance })\n }\n\n // 2. Push { node, index +1, tolerance -1 } (Delete operation)\n stack.push({ node: node, index: index + 1, tolerance: tolerance - 1 })\n\n // 3. For each child:\n for (const [character, childNode] of node.c) {\n // a) Insert operation\n stack.push({ node: childNode, index: index, tolerance: tolerance - 1 })\n\n // b) Substitute operation\n if (character !== currentChar) {\n stack.push({ node: childNode, index: index + 1, tolerance: tolerance - 1 })\n }\n }\n }\n }\n\n public find(params: FindParams): FindResult {\n const { term, exact, tolerance } = params\n if (tolerance && !exact) {\n const output: FindResult = {}\n this._findLevenshtein(term, 0, tolerance, tolerance, output)\n return output\n } else {\n let node: RadixNode = this\n let i = 0\n const termLength = term.length\n \n while (i < termLength) {\n const character = term[i]\n const childNode = node.c.get(character)\n \n if (childNode) {\n const edgeLabel = childNode.s\n const edgeLabelLength = edgeLabel.length\n let j = 0\n \n // Compare edge label with the term starting from position i\n while (j < edgeLabelLength && i + j < termLength && edgeLabel[j] === term[i + j]) {\n j++\n }\n \n if (j === edgeLabelLength) {\n // Full match of edge label; proceed to the child node\n node = childNode\n i += j\n } else if (i + j === termLength) {\n // The term ends in the middle of the edge label\n if (exact) {\n // Exact match required but term doesn't end at a node\n return {}\n } else {\n // Partial match; collect words starting from this node\n const output: FindResult = {}\n childNode.findAllWords(output, term, exact, tolerance)\n return output\n }\n } else {\n // Mismatch found\n return {}\n }\n } else {\n // No matching child node\n return {}\n }\n }\n \n // Term fully matched; collect words starting from this node\n const output: FindResult = {}\n node.findAllWords(output, term, exact, tolerance)\n return output\n }\n }\n \n public contains(term: string): boolean {\n let node: RadixNode = this\n let i = 0\n const termLength = term.length\n \n while (i < termLength) {\n const character = term[i]\n const childNode = node.c.get(character)\n \n if (childNode) {\n const edgeLabel = childNode.s\n const edgeLabelLength = edgeLabel.length\n let j = 0\n \n while (j < edgeLabelLength && i + j < termLength && edgeLabel[j] === term[i + j]) {\n j++\n }\n \n if (j < edgeLabelLength) {\n return false\n }\n \n i += edgeLabelLength\n node = childNode\n } else {\n return false\n }\n }\n return true\n } \n\n public removeWord(term: string): boolean {\n if (!term) {\n return false\n }\n\n let node: RadixNode = this\n const termLength = term.length\n const stack: { parent: RadixNode; character: string }[] = []\n for (let i = 0; i < termLength; i++) {\n const character = term[i]\n if (node.c.has(character)) {\n const childNode = node.c.get(character)!\n stack.push({ parent: node, character })\n i += childNode.s.length - 1\n node = childNode\n } else {\n return false\n }\n }\n\n // Remove documents from the node\n node.d.clear()\n node.e = false\n\n // Clean up any nodes that no longer lead to a word\n while (stack.length > 0 && node.c.size === 0 && !node.e && node.d.size === 0) {\n const { parent, character } = stack.pop()!\n parent.c.delete(character)\n node = parent\n }\n\n return true\n }\n\n public removeDocumentByWord(term: string, docID: InternalDocumentID, exact = true): boolean {\n if (!term) {\n return true\n }\n\n let node: RadixNode = this\n const termLength = term.length\n for (let i = 0; i < termLength; i++) {\n const character = term[i]\n if (node.c.has(character)) {\n const childNode = node.c.get(character)!\n i += childNode.s.length - 1\n node = childNode\n\n if (exact && node.w !== term) {\n // Do nothing if the exact condition is not met.\n } else {\n node.removeDocument(docID)\n }\n } else {\n return false\n }\n }\n return true\n }\n\n private static getCommonPrefix(a: string, b: string): string {\n const len = Math.min(a.length, b.length)\n let i = 0\n while (i < len && a.charCodeAt(i) === b.charCodeAt(i)) {\n i++\n }\n return a.slice(0, i)\n } \n\n public toJSON(): object {\n return {\n w: this.w,\n s: this.s,\n e: this.e,\n k: this.k,\n d: Array.from(this.d),\n c: Array.from(this.c?.entries())?.map(([key, node]) => [key, node.toJSON()])\n }\n }\n\n public static fromJSON(json: any): RadixNode {\n const node = new RadixNode(json.k, json.s, json.e)\n node.w = json.w\n node.d = new Set(json.d)\n node.c = new Map(json?.c?.map(([key, nodeJson]: [string, any]) => [key, RadixNode.fromJSON(nodeJson)]))\n return node\n }\n}\n\nexport class RadixTree extends RadixNode {\n constructor() {\n super('', '', false)\n }\n\n public static fromJSON(json: any): RadixTree {\n const tree = new RadixTree()\n tree.w = json.w\n tree.s = json.s\n tree.e = json.e\n tree.k = json.k\n tree.d = new Set(json.d)\n tree.c = new Map(json.c?.map(([key, nodeJson]: [string, any]) => [key, RadixNode.fromJSON(nodeJson)]))\n return tree\n }\n\n public toJSON(): object {\n return super.toJSON()\n }\n}","import type { Nullable, GenericSorting } from '../types.js'\nimport type { InternalDocumentID } from '../components/internal-document-id-store.js'\n\nexport interface Point {\n lon: number\n lat: number\n}\n\nexport interface GeoSearchResult {\n point: Point\n docIDs: InternalDocumentID[]\n}\n\nexport type SortGeoPoints = Nullable<GenericSorting>\n\ntype SearchTask = {\n node: Nullable<BKDNode>\n depth: number\n}\n\nconst K = 2 // 2D points\nconst EARTH_RADIUS = 6371e3 // Earth radius in meters\n\nclass BKDNode {\n point: Point\n docIDs: Set<InternalDocumentID>\n left: Nullable<BKDNode>\n right: Nullable<BKDNode>\n parent: Nullable<BKDNode>\n\n constructor(point: Point, docIDs?: InternalDocumentID[]) {\n this.point = point\n this.docIDs = new Set(docIDs)\n this.left = null\n this.right = null\n this.parent = null\n }\n\n toJSON(): any {\n return {\n point: this.point,\n docIDs: Array.from(this.docIDs),\n left: this.left ? this.left.toJSON() : null,\n right: this.right ? this.right.toJSON() : null\n }\n }\n\n static fromJSON(json: any, parent: Nullable<BKDNode> = null): BKDNode {\n const node = new BKDNode(json.point, json.docIDs)\n node.parent = parent\n if (json.left) {\n node.left = BKDNode.fromJSON(json.left, node)\n }\n if (json.right) {\n node.right = BKDNode.fromJSON(json.right, node)\n }\n return node\n }\n}\n\nexport class BKDTree {\n root: Nullable<BKDNode>\n nodeMap: Map<string, BKDNode>\n\n constructor() {\n this.root = null\n this.nodeMap = new Map()\n }\n\n private getPointKey(point: Point): string {\n return `${point.lon},${point.lat}`\n }\n\n insert(point: Point, docIDs: InternalDocumentID[]): void {\n const pointKey = this.getPointKey(point)\n const existingNode = this.nodeMap.get(pointKey)\n if (existingNode) {\n docIDs.forEach((id) => existingNode.docIDs.add(id))\n return\n }\n\n const newNode = new BKDNode(point, docIDs)\n this.nodeMap.set(pointKey, newNode)\n\n if (this.root == null) {\n this.root = newNode\n return\n }\n\n let node = this.root\n let depth = 0\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const axis = depth % K\n\n if (axis === 0) {\n if (point.lon < node.point.lon) {\n if (node.left == null) {\n node.left = newNode\n newNode.parent = node\n return\n }\n node = node.left\n } else {\n if (node.right == null) {\n node.right = newNode\n newNode.parent = node\n return\n }\n node = node.right\n }\n } else {\n if (point.lat < node.point.lat) {\n if (node.left == null) {\n node.left = newNode\n newNode.parent = node\n return\n }\n node = node.left\n } else {\n if (node.right == null) {\n node.right = newNode\n newNode.parent = node\n return\n }\n node = node.right\n }\n }\n\n depth++\n }\n }\n\n contains(point: Point): boolean {\n const pointKey = this.getPointKey(point)\n return this.nodeMap.has(pointKey)\n }\n\n getDocIDsByCoordinates(point: Point): Nullable<InternalDocumentID[]> {\n const pointKey = this.getPointKey(point)\n const node = this.nodeMap.get(pointKey)\n if (node) {\n return Array.from(node.docIDs)\n }\n return null\n }\n\n removeDocByID(point: Point, docID: InternalDocumentID): void {\n const pointKey = this.getPointKey(point)\n const node = this.nodeMap.get(pointKey)\n if (node) {\n node.docIDs.delete(docID)\n if (node.docIDs.size === 0) {\n this.nodeMap.delete(pointKey)\n this.deleteNode(node)\n }\n }\n }\n\n private deleteNode(node: BKDNode): void {\n const parent = node.parent\n const child = node.left ? node.left : node.right\n if (child) {\n child.parent = parent\n }\n\n if (parent) {\n if (parent.left === node) {\n parent.left = child\n } else if (parent.right === node) {\n parent.right = child\n }\n } else {\n this.root = child\n if (this.root) {\n this.root.parent = null\n }\n }\n }\n\n searchByRadius(\n center: Point,\n radius: number,\n inclusive = true,\n sort: SortGeoPoints = 'asc',\n highPrecision = false\n ): GeoSearchResult[] {\n const distanceFn = highPrecision ? BKDTree.vincentyDistance : BKDTree.haversineDistance\n const stack: Array<{ node: Nullable<BKDNode>; depth: number }> = [{ node: this.root, depth: 0 }]\n const result: GeoSearchResult[] = []\n\n while (stack.length > 0) {\n const { node, depth } = stack.pop()!\n if (node == null) continue\n\n const dist = distanceFn(center, node.point)\n\n if (inclusive ? dist <= radius : dist > radius) {\n result.push({ point: node.point, docIDs: Array.from(node.docIDs) })\n }\n\n if (node.left != null) {\n stack.push({ node: node.left, depth: depth + 1 })\n }\n if (node.right != null) {\n stack.push({ node: node.right, depth: depth + 1 })\n }\n }\n\n if (sort) {\n result.sort((a, b) => {\n const distA = distanceFn(center, a.point)\n const distB = distanceFn(center, b.point)\n return sort.toLowerCase() === 'asc' ? distA - distB : distB - distA\n })\n }\n\n return result\n }\n\n searchByPolygon(\n polygon: Point[],\n inclusive = true,\n sort: SortGeoPoints = null,\n highPrecision = false\n ): GeoSearchResult[] {\n const stack: SearchTask[] = [{ node: this.root, depth: 0 }]\n const result: GeoSearchResult[] = []\n\n while (stack.length > 0) {\n const { node, depth } = stack.pop()!\n if (node == null) continue\n\n if (node.left != null) {\n stack.push({ node: node.left, depth: depth + 1 })\n }\n if (node.right != null) {\n stack.push({ node: node.right, depth: depth + 1 })\n }\n\n const isInsidePolygon = BKDTree.isPointInPolygon(polygon, node.point)\n\n if ((isInsidePolygon && inclusive) || (!isInsidePolygon && !inclusive)) {\n result.push({ point: node.point, docIDs: Array.from(node.docIDs) })\n }\n }\n\n const centroid = BKDTree.calculatePolygonCentroid(polygon)\n\n if (sort) {\n const distanceFn = highPrecision ? BKDTree.vincentyDistance : BKDTree.haversineDistance\n result.sort((a, b) => {\n const distA = distanceFn(centroid, a.point)\n const distB = distanceFn(centroid, b.point)\n return sort!.toLowerCase() === 'asc' ? distA - distB : distB - distA\n })\n }\n\n return result\n }\n\n toJSON(): any {\n return {\n root: this.root ? this.root.toJSON() : null\n }\n }\n\n static fromJSON(json: any): BKDTree {\n const tree = new BKDTree()\n if (json.root) {\n tree.root = BKDNode.fromJSON(json.root)\n tree.buildNodeMap(tree.root)\n }\n return tree\n }\n\n private buildNodeMap(node: Nullable<BKDNode>): void {\n if (node == null) return\n const pointKey = this.getPointKey(node.point)\n this.nodeMap.set(pointKey, node)\n if (node.left) {\n this.buildNodeMap(node.left)\n }\n if (node.right) {\n this.buildNodeMap(node.right)\n }\n }\n\n static calculatePolygonCentroid(polygon: Point[]): Point {\n let totalArea = 0\n let centroidX = 0\n let centroidY = 0\n\n const polygonLength = polygon.length\n for (let i = 0, j = polygonLength - 1; i < polygonLength; j = i++) {\n const xi = polygon[i].lon\n const yi = polygon[i].lat\n const xj = polygon[j].lon\n const yj = polygon[j].lat\n\n const areaSegment = xi * yj - xj * yi\n totalArea += areaSegment\n\n centroidX += (xi + xj) * areaSegment\n centroidY += (yi + yj) * areaSegment\n }\n\n totalArea /= 2\n const centroidCoordinate = 6 * totalArea\n\n centroidX /= centroidCoordinate\n centroidY /= centroidCoordinate\n\n return { lon: centroidX, lat: centroidY }\n }\n\n static isPointInPolygon(polygon: Point[], point: Point): boolean {\n let isInside = false\n const x = point.lon\n const y = point.lat\n const polygonLength = polygon.length\n for (let i = 0, j = polygonLength - 1; i < polygonLength; j = i++) {\n const xi = polygon[i].lon\n const yi = polygon[i].lat\n const xj = polygon[j].lon\n const yj = polygon[j].lat\n\n const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi\n if (intersect) isInside = !isInside\n }\n\n return isInside\n }\n\n static haversineDistance(coord1: Point, coord2: Point): number {\n const P = Math.PI / 180\n const lat1 = coord1.lat * P\n const lat2 = coord2.lat * P\n const deltaLat = (coord2.lat - coord1.lat) * P\n const deltaLon = (coord2.lon - coord1.lon) * P\n\n const a =\n Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +\n Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2)\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))\n\n return EARTH_RADIUS * c\n }\n\n static vincentyDistance(coord1: Point, coord2: Point): number {\n const a = 6378137\n const f = 1 / 298.257223563\n const b = (1 - f) * a\n\n const P = Math.PI / 180\n const lat1 = coord1.lat * P\n const lat2 = coord2.lat * P\n const deltaLon = (coord2.lon - coord1.lon) * P\n\n const U1 = Math.atan((1 - f) * Math.tan(lat1))\n const U2 = Math.atan((1 - f) * Math.tan(lat2))\n\n const sinU1 = Math.sin(U1)\n const cosU1 = Math.cos(U1)\n const sinU2 = Math.sin(U2)\n const cosU2 = Math.cos(U2)\n\n let lambda = deltaLon\n let prevLambda\n let iterationLimit = 1000\n let sinSigma\n let cosSigma\n let sigma\n let sinAlpha\n let cos2Alpha\n let cos2SigmaM\n\n do {\n const sinLambda = Math.sin(lambda)\n const cosLambda = Math.cos(lambda)\n\n sinSigma = Math.sqrt(\n cosU2 * sinLambda * (cosU2 * sinLambda) +\n (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda)\n )\n\n if (sinSigma === 0) return 0 // co-incident points\n\n cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda\n sigma = Math.atan2(sinSigma, cosSigma)\n\n sinAlpha = (cosU1 * cosU2 * sinLambda) / sinSigma\n cos2Alpha = 1 - sinAlpha * sinAlpha\n cos2SigmaM = cosSigma - (2 * sinU1 * sinU2) / cos2Alpha\n\n if (isNaN(cos2SigmaM)) cos2SigmaM = 0\n\n const C = (f / 16) * cos2Alpha * (4 + f * (4 - 3 * cos2Alpha))\n prevLambda = lambda\n lambda =\n deltaLon +\n (1 - C) *\n f *\n sinAlpha *\n (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)))\n } while (Math.abs(lambda - prevLambda) > 1e-12 && --iterationLimit > 0)\n\n if (iterationLimit === 0) {\n return NaN\n }\n\n const uSquared = (cos2Alpha * (a * a - b * b)) / (b * b)\n const A = 1 + (uSquared / 16384) * (4096 + uSquared * (-768 + uSquared * (320 - 175 * uSquared)))\n const B = (uSquared / 1024) * (256 + uSquared * (-128 + uSquared * (74 - 47 * uSquared)))\n\n const deltaSigma =\n B *\n sinSigma *\n (cos2SigmaM +\n (B / 4) *\n (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -\n (B / 6) * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)))\n\n const s = b * A * (sigma - deltaSigma)\n\n return s\n }\n}\n","export class BoolNode<V = unknown> {\n true: Set<V>\n false: Set<V>\n\n constructor() {\n this.true = new Set()\n this.false = new Set()\n }\n\n insert(value: V, bool: boolean): void {\n if (bool) {\n this.true.add(value)\n } else {\n this.false.add(value)\n }\n }\n\n delete(value: V, bool: boolean): void {\n if (bool) {\n this.true.delete(value)\n } else {\n this.false.delete(value)\n }\n }\n\n getSize(): number {\n return this.true.size + this.false.size\n }\n\n toJSON(): any {\n return {\n true: Array.from(this.true),\n false: Array.from(this.false)\n }\n }\n\n static fromJSON<V>(json: any): BoolNode<V> {\n const node = new BoolNode<V>()\n node.true = new Set(json.true)\n node.false = new Set(json.false)\n return node\n }\n}\n","import { createError } from '../errors.js'\nimport { TokenScore, BM25Params } from '../types.js'\nimport { InternalDocumentID } from './internal-document-id-store.js'\n\nexport function prioritizeTokenScores(\n arrays: TokenScore[][],\n boost: number,\n threshold = 0,\n keywordsCount: number\n): TokenScore[] {\n if (boost === 0) {\n throw createError('INVALID_BOOST_VALUE')\n }\n\n const tokenScoresMap = new Map<InternalDocumentID, [number, number]>()\n\n const mapsLength = arrays.length\n for (let i = 0; i < mapsLength; i++) {\n const arr = arrays[i]\n\n const entriesLength = arr.length\n for (let j = 0; j < entriesLength; j++) {\n const [token, score] = arr[j]\n const boostScore = score * boost\n const oldScore = tokenScoresMap.get(token)?.[0]\n\n if (oldScore !== undefined) {\n tokenScoresMap.set(token, [oldScore * 1.5 + boostScore, (tokenScoresMap?.get(token)?.[1] || 0) + 1])\n } else {\n tokenScoresMap.set(token, [boostScore, 1])\n }\n }\n }\n\n const tokenScores: TokenScore[] = []\n\n for (const tokenScoreEntry of tokenScoresMap.entries()) {\n tokenScores.push([tokenScoreEntry[0], tokenScoreEntry[1][0]])\n }\n\n const results = tokenScores.sort((a, b) => b[1] - a[1])\n\n // If threshold is 1, it means we will return all the results with at least one search term,\n // prioritizig the ones that contains more search terms (fuzzy match)\n if (threshold === 1) {\n return results\n }\n\n // Prepare keywords count tracking for threshold handling\n const allResults = results.length\n const tokenScoreWithKeywordsCount: [InternalDocumentID, number, number][] = []\n\n for (const tokenScoreEntry of tokenScoresMap.entries()) {\n tokenScoreWithKeywordsCount.push([tokenScoreEntry[0], tokenScoreEntry[1][0], tokenScoreEntry[1][1]])\n }\n\n // Find the index of the last result with all keywords.\n // Order the documents by the number of keywords they contain, and then by the score.\n const keywordsPerToken = tokenScoreWithKeywordsCount.sort((a, b) => {\n // Compare by the third element, higher numbers first\n if (a[2] > b[2]) return -1\n if (a[2] < b[2]) return 1\n\n // If the third elements are equal, compare by the second element, higher numbers first\n if (a[1] > b[1]) return -1\n if (a[1] < b[1]) return 1\n\n // If both the second and third elements are equal, consider the elements equal\n return 0\n })\n\n let lastTokenWithAllKeywords: number | undefined = undefined\n for (let i = 0; i < allResults; i++) {\n if (keywordsPerToken[i][2] === keywordsCount) {\n lastTokenWithAllKeywords = i\n } else {\n break\n }\n }\n\n // If no results had all the keywords, either bail out earlier or normalize\n if (typeof lastTokenWithAllKeywords === 'undefined') {\n if (threshold === 0) {\n return []\n }\n\n lastTokenWithAllKeywords = 0\n }\n\n const keywordsPerTokenLength = keywordsPerToken.length\n const resultsWithIdAndScore: [number, number][] = new Array(keywordsPerTokenLength)\n for (let i = 0; i < keywordsPerTokenLength; i++) {\n resultsWithIdAndScore[i] = [keywordsPerToken[i][0], keywordsPerToken[i][1]]\n }\n\n // If threshold is 0, it means we will only return all the results that contains ALL the search terms (exact match)\n if (threshold === 0) {\n return resultsWithIdAndScore.slice(0, lastTokenWithAllKeywords + 1)\n }\n\n // If the threshold is between 0 and 1, we will return all the results that contains at least the threshold of search terms\n // For example, if threshold is 0.5, we will return all the results that contains at least 50% of the search terms\n // (fuzzy match with a minimum threshold)\n const thresholdLength =\n lastTokenWithAllKeywords + Math.ceil((threshold * 100 * (allResults - lastTokenWithAllKeywords)) / 100)\n\n return resultsWithIdAndScore.slice(0, allResults + thresholdLength)\n}\n\nexport function BM25(\n tf: number,\n matchingCount: number,\n docsCount: number,\n fieldLength: number,\n averageFieldLength: number,\n { k, b, d }: Required<BM25Params>\n) {\n const idf = Math.log(1 + (docsCount - matchingCount + 0.5) / (matchingCount + 0.5))\n return (idf * (d + tf * (k + 1))) / (tf + k * (1 - b + (b * fieldLength) / averageFieldLength))\n}\n","import { InternalDocumentID } from \"../components/internal-document-id-store.js\"\n\nexport type Magnitude = number\nexport type VectorType = Float32Array\nexport type VectorTypeLike = number[] | VectorType\n\nexport type SimilarVector = [number, number]\n\nexport const DEFAULT_SIMILARITY = 0.8\n\nexport class VectorIndex {\n private vectors: Map<InternalDocumentID, [Magnitude, VectorType]> = new Map()\n\n constructor(\n public size: number,\n ) {}\n\n add(internalDocumentId: InternalDocumentID, value: VectorTypeLike) {\n if (!(value instanceof Float32Array)) {\n value = new Float32Array(value)\n }\n\n const magnitude = getMagnitude(value, this.size)\n this.vectors.set(internalDocumentId, [magnitude, value])\n }\n\n remove(internalDocumentId: InternalDocumentID) {\n this.vectors.delete(internalDocumentId)\n }\n\n find(vector: VectorTypeLike, similarity: number, whereFiltersIDs: Set<InternalDocumentID> | undefined): SimilarVector[] {\n if (!(vector instanceof Float32Array)) {\n vector = new Float32Array(vector)\n }\n\n const results = findSimilarVectors(\n vector,\n whereFiltersIDs,\n this.vectors,\n this.size, similarity\n )\n\n return results\n }\n\n public toJSON(): { size: number, vectors: [InternalDocumentID, [Magnitude, number[]]][] } {\n const vectors: [InternalDocumentID, [Magnitude, number[]]][] = []\n\n for (const [id, [magnitude, vector]] of this.vectors) {\n vectors.push([id, [magnitude, Array.from(vector)]])\n }\n\n return {\n size: this.size,\n vectors,\n }\n }\n\n public static fromJSON(json: any): VectorIndex {\n const raw: { size: number, vectors: [InternalDocumentID, [Magnitude, number[]]][] } = json\n \n const index = new VectorIndex(raw.size)\n for (const [id, [magnitude, vector]] of raw.vectors) {\n index.vectors.set(id, [magnitude, new Float32Array(vector)])\n }\n\n return index\n }\n}\n\n\nexport function getMagnitude(vector: Float32Array, vectorLength: number): number {\n let magnitude = 0\n for (let i = 0; i < vectorLength; i++) {\n magnitude += vector[i] * vector[i]\n }\n return Math.sqrt(magnitude)\n}\n\n// @todo: Write plugins for Node and Browsers to use parallel computation for this function\nexport function findSimilarVectors(\n targetVector: Float32Array,\n keys: Set<InternalDocumentID> | undefined,\n vectors: Map<InternalDocumentID, [Magnitude, VectorType]>,\n length: number,\n threshold\n): SimilarVector[] {\n const targetMagnitude = getMagnitude(targetVector, length)\n\n const similarVectors: SimilarVector[] = []\n\n const base = keys ? keys : vectors.keys()\n for (const vectorId of base) {\n const entry = vectors.get(vectorId)\n if (!entry) {\n continue\n }\n const magnitude = entry[0]\n const vector = entry[1]\n\n let dotProduct = 0\n for (let i = 0; i < length; i++) {\n dotProduct += targetVector[i] * vector[i]\n }\n\n const similarity = dotProduct / (targetMagnitude * magnitude)\n\n if (similarity >= threshold) {\n similarVectors.push([vectorId, similarity])\n }\n }\n\n return similarVectors\n}\n","// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\n\nconst step2List = {\n ational: 'ate',\n tional: 'tion',\n enci: 'ence',\n anci: 'ance',\n izer: 'ize',\n bli: 'ble',\n alli: 'al',\n entli: 'ent',\n eli: 'e',\n ousli: 'ous',\n ization: 'ize',\n ation: 'ate',\n ator: 'ate',\n alism: 'al',\n iveness: 'ive',\n fulness: 'ful',\n ousness: 'ous',\n aliti: 'al',\n iviti: 'ive',\n biliti: 'ble',\n logi: 'log'\n}\n\nconst step3List = {\n icate: 'ic',\n ative: '',\n alize: 'al',\n iciti: 'ic',\n ical: 'ic',\n ful: '',\n ness: ''\n}\n\n// Consonant\nconst c = '[^aeiou]'\n// Vowel\nconst v = '[aeiouy]'\n// Consonant sequence\nconst C = c + '[^aeiouy]*'\n// Vowel sequence\nconst V = v + '[aeiou]*'\n\n// [C]VC... is m>0\nconst mgr0 = '^(' + C + ')?' + V + C\n// [C]VC[V] is m=1\nconst meq1 = '^(' + C + ')?' + V + C + '(' + V + ')?$'\n// [C]VCVC... is m>1\nconst mgr1 = '^(' + C + ')?' + V + C + V + C\n// vowel in stem\nconst s_v = '^(' + C + ')?' + v\n\nexport function stemmer(w) {\n let stem\n let suffix\n let re\n let re2\n let re3\n let re4\n\n if (w.length < 3) {\n return w\n }\n\n const firstch = w.substring(0, 1)\n if (firstch == 'y') {\n w = firstch.toUpperCase() + w.substring(1)\n }\n\n re = /^(.+?)(ss|i)es$/\n re2 = /^(.+?)([^s])s$/\n\n if (re.test(w)) {\n w = w.replace(re, '$1$2')\n } else if (re2.test(w)) {\n w = w.replace(re2, '$1$2')\n }\n\n re = /^(.+?)eed$/\n re2 = /^(.+?)(ed|ing)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n re = new RegExp(mgr0)\n if (re.test(fp[1])) {\n re = /.$/\n w = w.replace(re, '')\n }\n } else if (re2.test(w)) {\n const fp = re2.exec(w)\n stem = fp[1]\n re2 = new RegExp(s_v)\n if (re2.test(stem)) {\n w = stem\n re2 = /(at|bl|iz)$/\n re3 = new RegExp('([^aeiouylsz])\\\\1$')\n re4 = new RegExp('^' + C + v + '[^aeiouwxy]$')\n if (re2.test(w)) {\n w = w + 'e'\n } else if (re3.test(w)) {\n re = /.$/\n w = w.replace(re, '')\n } else if (re4.test(w)) {\n w = w + 'e'\n }\n }\n }\n\n re = /^(.+?)y$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n re = new RegExp(s_v)\n if (stem && re.test(stem)) {\n w = stem + 'i'\n }\n }\n\n re =\n /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n suffix = fp?.[2]\n re = new RegExp(mgr0)\n if (stem && re.test(stem)) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n w = stem + step2List[suffix]\n }\n }\n\n re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n suffix = fp?.[2]\n re = new RegExp(mgr0)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (stem && re.test(stem)) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n w = stem + step3List[suffix]\n }\n }\n\n re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/\n re2 = /^(.+?)(s|t)(ion)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n re = new RegExp(mgr1)\n if (stem && re.test(stem)) {\n w = stem\n }\n } else if (re2.test(w)) {\n const fp = re2.exec(w)\n stem = fp?.[1] ?? '' + fp?.[2] ?? ''\n re2 = new RegExp(mgr1)\n if (re2.test(stem)) {\n w = stem\n }\n }\n\n re = /^(.+?)e$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n re = new RegExp(mgr1)\n re2 = new RegExp(meq1)\n re3 = new RegExp('^' + C + v + '[^aeiouwxy]$')\n if (stem && (re.test(stem) || (re2.test(stem) && !re3.test(stem)))) {\n w = stem\n }\n }\n\n re = /ll$/\n re2 = new RegExp(mgr1)\n if (re.test(w) && re2.test(w)) {\n re = /.$/\n w = w.replace(re, '')\n }\n\n if (firstch == 'y') {\n w = firstch.toLowerCase() + w.substring(1)\n }\n\n return w\n}\n","import { AnyIndexStore, AnyOrama, SearchableType, Tokenizer } from \"@orama/orama\"\nimport { avl, bkd, flat, bool, vector } from '@orama/orama/trees'\nimport {\n getVectorSize, internalDocumentIDStore, isVectorType } from '@orama/orama/components'\n\ntype InternalDocumentID = internalDocumentIDStore.InternalDocumentID;\n\nexport type TreeType = 'AVL' | 'Radix' | 'Bool' | 'Flat' | 'BKD';\nexport type TTree<T = TreeType, N = unknown> = {\n type: T;\n node: N;\n isArray: boolean;\n};\nexport type Tree =\n // We don't store strings inside a tree\n // | TTree<'Radix', radix.RadixNode>\n | TTree<'Position', PositionsStorage>\n | TTree<'AVL', avl.AVLTree<number, InternalDocumentID[]>>\n | TTree<'Bool', bool.BoolNode>\n | TTree<'Flat', flat.FlatTree>\n | TTree<'BKD', bkd.BKDTree>;\n\nconst MAX_POSITION = 15\nexport type PositionStorage = Record<string, number[]>\n// 15 `PositionStorage`s\nexport type PositionsStorage = [\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n]\n\nexport interface PT15IndexStore extends AnyIndexStore {\n indexes: Record<string, Tree>\n searchableProperties: string[]\n searchablePropertiesWithTypes: Record<string, SearchableType>\n}\n\nfunction create_obj() {\n // object with empty prototype to cheap objects\n return Object.create(null)\n}\n\nexport function recursiveCreate<T extends AnyOrama>(indexDatastore: PT15IndexStore, schema: T['schema'], prefix: string) {\n for (const [prop, type] of Object.entries<SearchableType>(schema)) {\n const path = `${prefix}${prefix ? '.' : ''}${prop}`\n\n if (typeof type === 'object' && !Array.isArray(type)) {\n // Nested\n recursiveCreate(indexDatastore, type, path)\n continue\n }\n\n if (isVectorType(type)) {\n indexDatastore.searchableProperties.push(path)\n indexDatastore.searchablePropertiesWithTypes[path] = type\n indexDatastore.vectorIndexes[path] = {\n type: 'Vector',\n node: new vector.VectorIndex(getVectorSize(type)),\n isArray: false,\n }\n } else {\n const isArray = /\\[/.test(type as string)\n switch (type) {\n case 'boolean':\n case 'boolean[]':\n indexDatastore.indexes[path] = { type: 'Bool', node: new bool.BoolNode(), isArray }\n break\n case 'number':\n case 'number[]':\n indexDatastore.indexes[path] = { type: 'AVL', node: new avl.AVLTree<number, InternalDocumentID[]>(0, []), isArray }\n break\n case 'string':\n case 'string[]':\n indexDatastore.indexes[path] = { type: 'Position', node: [\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n ], isArray }\n break\n case 'enum':\n case 'enum[]':\n indexDatastore.indexes[path] = { type: 'Flat', node: new flat.FlatTree(), isArray }\n break\n case 'geopoint':\n indexDatastore.indexes[path] = { type: 'BKD', node: new bkd.BKDTree(), isArray }\n break\n default:\n throw new Error('INVALID_SCHEMA_TYPE: ' + path)\n }\n\n indexDatastore.searchableProperties.push(path)\n indexDatastore.searchablePropertiesWithTypes[path] = type\n }\n }\n}\n\nexport function insertString(\n value: string,\n positionsStorage: PositionsStorage,\n prop: string,\n internalId: InternalDocumentID,\n language: string | undefined,\n tokenizer: Tokenizer,\n) {\n const tokens = tokenizer.tokenize(value, language, prop)\n const tokensLength = tokens.length\n for (let i = 0; i < tokensLength; i++) {\n const token = tokens[i]\n const position = MAX_POSITION - get_position(i, tokensLength) - 1\n\n const positionStorage = positionsStorage[position]\n\n const tokenLength = token.length\n for (let j = tokenLength; j > 0; j--) {\n const tokenPart = token.slice(0, j)\n positionStorage[tokenPart] = positionStorage[tokenPart] || []\n positionStorage[tokenPart].push(internalId)\n }\n }\n}\n\nexport function get_position(n: number, totalLength: number) {\n if (totalLength < MAX_POSITION) {\n return n\n }\n // Scale\n return Math.floor(n * MAX_POSITION / totalLength) \n}\n\nexport function searchString(\n tokenizer: Tokenizer,\n term: string,\n positionsStorage: PositionsStorage,\n boostPerProp: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined,\n) {\n const tokens = tokenizer.tokenize(term)\n\n const ret: Map<number, number> = new Map()\n for (const token of tokens) {\n for (let i = 0; i < MAX_POSITION; i++) {\n const positionStorage = positionsStorage[i]\n if (positionStorage[token]) {\n const a = positionStorage[token]\n const aLength = a.length\n\n for (let j = 0; j < aLength; j++) {\n if (whereFiltersIDs && !whereFiltersIDs.has(a[j])) {\n continue\n }\n\n const id = a[j]\n if (ret.has(id)) {\n ret.set(id, ret.get(id)! + i * boostPerProp)\n } else {\n ret.set(id, i * boostPerProp)\n }\n }\n }\n }\n }\n\n return ret\n}\n\nexport function removeString(\n value: string,\n positionsStorage: PositionsStorage,\n prop: string,\n internalId: InternalDocumentID,\n tokenizer: Tokenizer,\n language: string | undefined,\n) {\n const tokens = tokenizer.tokenize(value, language, prop)\n const tokensLength = tokens.length\n for (let i = 0; i < tokensLength; i++) {\n const token = tokens[i]\n const position = MAX_POSITION - get_position(i, tokensLength) - 1\n\n const positionStorage = positionsStorage[position]\n\n const tokenLength = token.length\n for (let j = tokenLength; j > 0; j--) {\n const tokenPart = token.slice(0, j)\n const a = positionStorage[tokenPart]\n if (a) {\n const index = a.indexOf(internalId)\n if (index !== -1) {\n a.splice(index, 1)\n }\n }\n }\n }\n\n}"],"mappings":"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","names":["src_exports","__export","pluginPT15","STEMMERS","SUPPORTED_LANGUAGES","STEMMERS","baseId","nano","milli","second","sprintf","template","args","replaceArgs","groups","rawWidth","type","position","replacement","width","value","padding","precision","w","getOwnProperty","object","property","mapDistanceToMeters","convertDistanceToMeters","distance","unit","ratio","createError","withIntersection","setIntersection","sets","set1","set2","result","base","other","value","min","i","withUnion","setUnion","allLanguages","SUPPORTED_LANGUAGES","errors","createError","code","args","error","sprintf","IS_ARRAY_TYPE","INNER_TYPE","isVectorType","type","isArrayType","IS_ARRAY_TYPE","getInnerType","INNER_TYPE","getVectorSize","size","createError","getInternalDocumentId","store","id","internalId","currentId","components_exports","__export","calculateResultScores","create","createIndex","getSearchableProperties","getSearchablePropertiesWithTypes","insert","insertDocumentScoreParameters","insertTokenScoreParameters","insertVector","load","remove","removeDocumentScoreParameters","removeTokenScoreParameters","save","search","searchByWhereClause","avl_exports","__export","AVLNode","AVLTree","AVLNode","_AVLNode","key","value","__publicField","node","newRoot","json","AVLTree","_AVLTree","rebalanceThreshold","v","tree","path","current","parent","needRebalance","i","currentNode","rebalancedNode","balanceFactor","count","stack","id","child","successorParent","successor","min","max","result","setUnion","inclusive","flat_exports","__export","FlatTree","FlatTree","_FlatTree","__publicField","key","value","idSet","id","size","operation","operationKeys","operationType","values","resultSet","excludeValues","idSets","intersection","prev","curr","json","tree","ids","_boundedLevenshtein","term","word","tolerance","m","n","diff","matrix","i","j","rowMin","syncBoundedLevenshtein","term","w","tolerance","distance","_boundedLevenshtein","RadixNode","_RadixNode","key","subWord","end","__publicField","parent","docID","output","term","exact","tolerance","stack","node","w","docIDs","getOwnProperty","syncBoundedLevenshtein","docs","word","docId","i","wordLength","currentCharacter","childNode","edgeLabel","edgeLabelLength","j","commonPrefix","newEdgeLabel","newWordLabel","inbetweenNode","newNode","index","originalTolerance","currentChar","character","params","termLength","a","b","len","json","nodeJson","RadixTree","_RadixTree","tree","bkd_exports","__export","BKDTree","BKDNode","_BKDNode","point","docIDs","__publicField","json","parent","node","BKDTree","_BKDTree","pointKey","existingNode","id","newNode","depth","docID","child","center","radius","inclusive","sort","highPrecision","distanceFn","stack","result","dist","a","b","distA","distB","polygon","isInsidePolygon","centroid","tree","totalArea","centroidX","centroidY","polygonLength","i","j","xi","yi","xj","yj","areaSegment","centroidCoordinate","isInside","x","y","coord1","coord2","P","lat1","lat2","deltaLat","deltaLon","f","U1","U2","sinU1","cosU1","sinU2","cosU2","lambda","prevLambda","iterationLimit","sinSigma","cosSigma","sigma","sinAlpha","cos2Alpha","cos2SigmaM","sinLambda","cosLambda","C","uSquared","A","B","deltaSigma","bool_exports","__export","BoolNode","BoolNode","_BoolNode","__publicField","value","bool","json","node","BM25","tf","matchingCount","docsCount","fieldLength","averageFieldLength","k","b","d","vector_exports","__export","DEFAULT_SIMILARITY","VectorIndex","findSimilarVectors","getMagnitude","DEFAULT_SIMILARITY","VectorIndex","_VectorIndex","size","__publicField","internalDocumentId","value","magnitude","getMagnitude","vector","similarity","whereFiltersIDs","findSimilarVectors","vectors","id","json","raw","index","vectorLength","i","targetVector","keys","length","threshold","targetMagnitude","similarVectors","base","vectorId","entry","dotProduct","insertDocumentScoreParameters","index","prop","id","tokens","docsCount","internalId","getInternalDocumentId","insertTokenScoreParameters","token","tokenFrequency","t","tf","removeDocumentScoreParameters","removeTokenScoreParameters","create","orama","sharedInternalDocumentStore","schema","prefix","type","path","isVectorType","VectorIndex","getVectorSize","isArray","BoolNode","AVLTree","RadixTree","FlatTree","BKDTree","createError","insertScalarBuilder","implementation","language","tokenizer","options","value","node","avlRebalanceThreshold","insert","schemaType","insertVector","insertScalar","isArrayType","elements","elementsLength","i","internalDocumentId","removeScalar","remove","innerSchemaType","getInnerType","calculateResultScores","term","ids","bm25Relevance","resultsMap","boostPerProperty","whereFiltersIDs","documentIDs","avgFieldLength","fieldLengths","oramaOccurrences","oramaFrequencies","termOccurrences","documentIDsLength","k","bm25","BM25","searchInProperty","tree","exact","tolerance","tokenLength","searchResult","termsFound","termsFoundLength","j","word","search","propertiesToSearch","boost","relevance","searchByWhereClause","filters","filterKeys","filtersMap","acc","key","param","operation","idx","filteredIDs","setUnion","reqOperation","coordinates","unit","inside","highPrecision","distanceInMeters","convertDistanceToMeters","addGeoResult","raw","filteredIDsResults","addFindResult","operationKeys","results","operationOpt","operationValue","min","max","setIntersection","getSearchableProperties","getSearchablePropertiesWithTypes","load","rawIndexes","rawVectorIndexes","searchableProperties","searchablePropertiesWithTypes","frequencies","tokenOccurrences","indexes","vectorIndexes","save","dumpVectorIndexes","savedIndexes","name","createIndex","set","idsLength","entry","keys","keysLength","c","v","C","mgr0","meq1","mgr1","s_v","MAX_POSITION","create_obj","recursiveCreate","indexDatastore","schema","prefix","prop","type","path","isVectorType","vector_exports","getVectorSize","isArray","bool_exports","avl_exports","flat_exports","bkd_exports","insertString","value","positionsStorage","internalId","language","tokenizer","tokens","tokensLength","i","token","position","get_position","positionStorage","tokenLength","j","tokenPart","n","totalLength","searchString","term","boostPerProp","whereFiltersIDs","ret","a","aLength","id","removeString","index","pluginPT15","schema","createComponents","indexDatastore","recursiveCreate","implementation","indexDatastorage","prop","id","internalId","value","schemaType","language","tokenizer","docsCount","components_exports","storage","item","insertString","removeString","index","term","propertiesToSearch","exact","tolerance","boost","relevance","whereFiltersIDs","maps","propertyLength","max","i","property","boostPerProp","map","searchString","base","score","filters","propName","sharedInternalDocumentStore","raw","dump1","dump2","baseIndex","nonStringIndexes","type","stringIndexes"]}
1
+ {"version":3,"sources":["../src/index.ts","../../orama/src/components/tokenizer/languages.ts","../../orama/src/utils.ts","../../orama/src/errors.ts","../../orama/src/components/defaults.ts","../../orama/src/components/internal-document-id-store.ts","../../orama/src/components/index.ts","../../orama/src/trees/avl.ts","../../orama/src/trees/flat.ts","../../orama/src/components/levenshtein.ts","../../orama/src/trees/radix.ts","../../orama/src/trees/bkd.ts","../../orama/src/trees/bool.ts","../../orama/src/components/algorithms.ts","../../orama/src/trees/vector.ts","../../orama/src/components/tokenizer/english-stemmer.ts","../src/algorithm.ts"],"sourcesContent":["import type { AnyOrama, SearchableType, IIndex, SearchableValue, Tokenizer, OnlyStrings, FlattenSchemaProperty, TokenScore, WhereCondition, OramaPluginSync, AnySchema, ObjectComponents, BM25Params } from '@orama/orama'\nimport {\n index as Index, internalDocumentIDStore } from '@orama/orama/components'\nimport { PT15IndexStore, insertString, recursiveCreate, PositionsStorage, searchString, removeString } from './algorithm.js';\n\ntype InternalDocumentID = internalDocumentIDStore.InternalDocumentID;\ntype InternalDocumentIDStore = internalDocumentIDStore.InternalDocumentIDStore;\ntype DocumentID = internalDocumentIDStore.DocumentID;\n\nexport function pluginPT15(): OramaPluginSync {\n\n return {\n name: 'orama-plugin-pt15',\n\n getComponents: function getComponents(schema: AnySchema) {\n return createComponents(schema)\n },\n }\n}\n\nfunction createComponents(schema: AnySchema): Partial<ObjectComponents<any, any, any>> {\n return {\n index: {\n create: function create() {\n const indexDatastore: PT15IndexStore = {\n indexes: {},\n vectorIndexes: {},\n searchableProperties: [],\n searchablePropertiesWithTypes: {},\n }\n\n recursiveCreate(indexDatastore, schema, '')\n\n return indexDatastore\n },\n insert: function insert(\n implementation: IIndex<PT15IndexStore>,\n indexDatastorage: PT15IndexStore,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n ) {\n if (!(schemaType === 'string' || schemaType === 'string[]')) {\n return Index.insert(implementation as unknown as IIndex<Index.Index>, indexDatastorage as unknown as Index.Index, prop, id, internalId, value, schemaType, language, tokenizer, docsCount)\n }\n\n const storage = indexDatastorage.indexes[prop].node as PositionsStorage\n\n if (Array.isArray(value)) {\n for (const item of value) {\n insertString(\n item as string,\n storage,\n prop,\n internalId,\n language,\n tokenizer,\n )\n }\n } else {\n insertString(\n value as string,\n storage,\n prop,\n internalId,\n language,\n tokenizer,\n )\n }\n },\n // remove: <T extends I>(implementation: IIndex<T>, index: T, prop: string, id: DocumentID, value: SearchableValue, schemaType: SearchableType, language: string | undefined, tokenizer: Tokenizer, docsCount: number) => SyncOrAsyncValue<boolean>;\n remove: function remove(implementation: IIndex<PT15IndexStore>, indexDatastorage: PT15IndexStore, prop: string, id: DocumentID, internalId: InternalDocumentID, value: SearchableValue, schemaType: SearchableType, language: string | undefined, tokenizer: Tokenizer, docsCount: number) {\n if (!(schemaType === 'string' || schemaType === 'string[]')) {\n return Index.remove(implementation as IIndex<Index.Index>, indexDatastorage as Index.Index, prop, id, internalId, value, schemaType, language, tokenizer, docsCount)\n }\n\n const storage = indexDatastorage.indexes[prop].node as PositionsStorage\n\n if (Array.isArray(value)) {\n for (const item of value) {\n removeString(\n item as string,\n storage,\n prop,\n internalId,\n tokenizer,\n language\n )\n }\n } else {\n removeString(\n value as string,\n storage,\n prop,\n internalId,\n tokenizer,\n language\n )\n }\n\n return true\n },\n insertDocumentScoreParameters: () => {throw new Error()},\n insertTokenScoreParameters: () => {throw new Error()},\n removeDocumentScoreParameters: () => {throw new Error()},\n removeTokenScoreParameters: () => {throw new Error()},\n calculateResultScores: () => {throw new Error()},\n search: function search<T extends AnyOrama>(index: PT15IndexStore, term: string, tokenizer: Tokenizer, language: string | undefined, propertiesToSearch: string[], exact: boolean, tolerance: number, boost: Partial<Record<OnlyStrings<FlattenSchemaProperty<T>[]>, number>>, relevance: Required<BM25Params>, docsCount: number, whereFiltersIDs: Set<InternalDocumentID> | undefined): TokenScore[] {\n if (tolerance !== 0) {\n throw new Error('Tolerance not implemented yet')\n }\n if (exact === true) {\n throw new Error('Exact not implemented yet')\n }\n\n const maps: Map<number, number>[] = []\n const propertyLength = propertiesToSearch.length\n let max = {\n score: -Infinity,\n id: -1\n }\n for (let i = 0; i < propertyLength; i++) {\n const property = propertiesToSearch[i]\n const storage = index.indexes[property].node as PositionsStorage\n const boostPerProp = boost[property] ?? 1\n const map = searchString(tokenizer, term, storage, boostPerProp, whereFiltersIDs);\n if (map.size > max.score) {\n max = {\n score: map.size,\n id: i\n }\n }\n maps.push(map)\n }\n\n if (maps.length === 1) {\n return Array.from(maps[0])\n }\n\n const base = maps[max.id]\n for (let i = 0; i < maps.length; i++) {\n if (i === max.id) {\n continue\n }\n\n const map = maps[i]\n for (const [id, score] of map) {\n if (base.has(id)) {\n base.set(id, base.get(id)! + score)\n } else {\n base.set(id, score)\n }\n }\n }\n \n return Array.from(base)\n },\n searchByWhereClause: function searchByWhereClause<T extends AnyOrama>(index: PT15IndexStore, tokenizer: Tokenizer, filters: Partial<WhereCondition<T['schema']>>, language: string | undefined) {\n const stringFiltersList = Object.entries(filters).filter(([propName]) => index.indexes[propName].type === 'Position')\n\n // PT15 doen't support string filters.\n // this plugin doesn't distringuish between prefix and exact match.\n if (stringFiltersList.length !== 0) {\n throw new Error('String filters are not supported')\n }\n\n return Index.searchByWhereClause(index as Index.Index, tokenizer, filters, language)\n },\n getSearchableProperties: function getSearchableProperties(index: PT15IndexStore): string[] {\n return index.searchableProperties\n },\n getSearchablePropertiesWithTypes: function (index: PT15IndexStore) {\n return index.searchablePropertiesWithTypes\n },\n load: function load<R = unknown>(sharedInternalDocumentStore: InternalDocumentIDStore, raw: R): PT15IndexStore {\n const dump1 = Index.load(sharedInternalDocumentStore, raw[0])\n const dump2 = raw[1]\n return {\n ...dump1,\n indexes: {\n ...Object.fromEntries(dump2),\n ...dump1.indexes\n } as PT15IndexStore['indexes']\n }\n },\n save: function save<R = unknown>(index: PT15IndexStore): R {\n const baseIndex = index as unknown as Index.Index\n const nonStringIndexes = Object.entries(index.indexes).filter(([, { type }]) => type !== 'Position')\n const dump1 = Index.save({\n ...baseIndex,\n indexes: Object.fromEntries(nonStringIndexes) as Index.Index['indexes']\n })\n\n const stringIndexes = Object.entries(index.indexes).filter(([, { type }]) => type === 'Position')\n\n return [dump1, stringIndexes] as unknown as R\n }\n }\n }\n}\n","export const STEMMERS: Record<string, string> = {\n arabic: 'ar',\n armenian: 'am',\n bulgarian: 'bg',\n danish: 'dk',\n dutch: 'nl',\n english: 'en',\n finnish: 'fi',\n french: 'fr',\n german: 'de',\n greek: 'gr',\n hungarian: 'hu',\n indian: 'in',\n indonesian: 'id',\n irish: 'ie',\n italian: 'it',\n lithuanian: 'lt',\n nepali: 'np',\n norwegian: 'no',\n portuguese: 'pt',\n romanian: 'ro',\n russian: 'ru',\n serbian: 'rs',\n slovenian: 'ru',\n spanish: 'es',\n swedish: 'se',\n tamil: 'ta',\n turkish: 'tr',\n ukrainian: 'uk',\n sanskrit: 'sk'\n}\n\nexport const SPLITTERS: Record<Language, RegExp> = {\n dutch: /[^A-Za-zàèéìòóù0-9_'-]+/gim,\n english: /[^A-Za-zàèéìòóù0-9_'-]+/gim,\n french: /[^a-z0-9äâàéèëêïîöôùüûœç-]+/gim,\n italian: /[^A-Za-zàèéìòóù0-9_'-]+/gim,\n norwegian: /[^a-z0-9_æøåÆØÅäÄöÖüÜ]+/gim,\n portuguese: /[^a-z0-9à-úÀ-Ú]/gim,\n russian: /[^a-z0-9а-яА-ЯёЁ]+/gim,\n spanish: /[^a-z0-9A-Zá-úÁ-ÚñÑüÜ]+/gim,\n swedish: /[^a-z0-9_åÅäÄöÖüÜ-]+/gim,\n german: /[^a-z0-9A-ZäöüÄÖÜß]+/gim,\n finnish: /[^a-z0-9äöÄÖ]+/gim,\n danish: /[^a-z0-9æøåÆØÅ]+/gim,\n hungarian: /[^a-z0-9áéíóöőúüűÁÉÍÓÖŐÚÜŰ]+/gim,\n romanian: /[^a-z0-9ăâîșțĂÂÎȘȚ]+/gim,\n serbian: /[^a-z0-9čćžšđČĆŽŠĐ]+/gim,\n turkish: /[^a-z0-9çÇğĞıİöÖşŞüÜ]+/gim,\n lithuanian: /[^a-z0-9ąčęėįšųūžĄČĘĖĮŠŲŪŽ]+/gim,\n arabic: /[^a-z0-9أ-ي]+/gim,\n nepali: /[^a-z0-9अ-ह]+/gim,\n irish: /[^a-z0-9áéíóúÁÉÍÓÚ]+/gim,\n indian: /[^a-z0-9अ-ह]+/gim,\n armenian: /[^a-z0-9ա-ֆ]+/gim,\n greek: /[^a-z0-9α-ωά-ώ]+/gim,\n indonesian: /[^a-z0-9]+/gim,\n ukrainian: /[^a-z0-9а-яА-ЯіїєІЇЄ]+/gim,\n slovenian: /[^a-z0-9螚ȎŠ]+/gim,\n bulgarian: /[^a-z0-9а-яА-Я]+/gim,\n tamil: /[^a-z0-9அ-ஹ]+/gim,\n sanskrit: /[^a-z0-9A-Zāīūṛḷṃṁḥśṣṭḍṇṅñḻḹṝ]+/gim\n}\n\nexport const SUPPORTED_LANGUAGES = Object.keys(STEMMERS)\n\nexport function getLocale(language: string | undefined) {\n return language !== undefined && SUPPORTED_LANGUAGES.includes(language) ? STEMMERS[language] : undefined\n}\n\nexport type Language = (typeof SUPPORTED_LANGUAGES)[number]\n","import type { AnyDocument, GeosearchDistanceUnit, Optional, Results, SearchableValue, TokenScore } from './types.js'\nimport { createError } from './errors.js'\n\nconst baseId = Date.now().toString().slice(5)\nlet lastId = 0\n\nconst k = 1024\nconst nano = BigInt(1e3)\nconst milli = BigInt(1e6)\nconst second = BigInt(1e9)\n\nexport const isServer = typeof window === 'undefined'\n\n/**\n * This value can be increased up to 100_000\n * But i don't know if this value change from nodejs to nodejs\n * So I will keep a safer value here.\n */\nexport const MAX_ARGUMENT_FOR_STACK = 65535\n\n/**\n * This method is needed to used because of issues like: https://github.com/oramasearch/orama/issues/301\n * that issue is caused because the array that is pushed is huge (>100k)\n *\n * @example\n * ```ts\n * safeArrayPush(myArray, [1, 2])\n * ```\n */\nexport function safeArrayPush<T>(arr: T[], newArr: T[]): void {\n if (newArr.length < MAX_ARGUMENT_FOR_STACK) {\n Array.prototype.push.apply(arr, newArr)\n } else {\n const newArrLength = newArr.length\n for (let i = 0; i < newArrLength; i += MAX_ARGUMENT_FOR_STACK) {\n Array.prototype.push.apply(arr, newArr.slice(i, i + MAX_ARGUMENT_FOR_STACK))\n }\n }\n}\n\nexport function sprintf(template: string, ...args: Array<string | number>): string {\n return template.replace(\n /%(?:(?<position>\\d+)\\$)?(?<width>-?\\d*\\.?\\d*)(?<type>[dfs])/g,\n function (...replaceArgs: Array<string | number | Record<string, string>>): string {\n const groups = replaceArgs[replaceArgs.length - 1] as Record<string, string>\n const { width: rawWidth, type, position } = groups\n\n const replacement = position ? args[Number.parseInt(position) - 1]! : args.shift()!\n const width = rawWidth === '' ? 0 : Number.parseInt(rawWidth)\n\n switch (type) {\n case 'd':\n return replacement.toString().padStart(width, '0')\n case 'f': {\n let value = replacement\n const [padding, precision] = rawWidth.split('.').map((w) => Number.parseFloat(w))\n\n if (typeof precision === 'number' && precision >= 0) {\n value = (value as number).toFixed(precision)\n }\n\n return typeof padding === 'number' && padding >= 0 ? value.toString().padStart(width, '0') : value.toString()\n }\n case 's':\n return width < 0\n ? (replacement as string).toString().padEnd(-width, ' ')\n : (replacement as string).toString().padStart(width, ' ')\n\n default:\n return replacement as string\n }\n }\n )\n}\n\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) {\n return '0 Bytes'\n }\n const dm = decimals < 0 ? 0 : decimals\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']\n const i = Math.floor(Math.log(bytes) / Math.log(k))\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`\n}\n\nexport function isInsideWebWorker(): boolean {\n // @ts-expect-error - WebWorker global scope\n return typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope\n}\n\nexport function isInsideNode(): boolean {\n return typeof process !== 'undefined' && process.release && process.release.name === 'node'\n}\n\nexport function getNanosecondTimeViaPerformance() {\n return BigInt(Math.floor(performance.now() * 1e6))\n}\n\nexport function formatNanoseconds(value: number | bigint): string {\n if (typeof value === 'number') {\n value = BigInt(value)\n }\n\n if (value < nano) {\n return `${value}ns`\n } else if (value < milli) {\n return `${value / nano}μs`\n } else if (value < second) {\n return `${value / milli}ms`\n }\n\n return `${value / second}s`\n}\n\nexport function getNanosecondsTime(): bigint {\n if (isInsideWebWorker()) {\n return getNanosecondTimeViaPerformance()\n }\n\n if (isInsideNode()) {\n return process.hrtime.bigint()\n }\n\n if (typeof process !== 'undefined' && typeof process?.hrtime?.bigint === 'function') {\n return process.hrtime.bigint()\n }\n\n if (typeof performance !== 'undefined') {\n return getNanosecondTimeViaPerformance()\n }\n\n // @todo: fallback to V8 native method to get microtime\n return BigInt(0)\n}\n\nexport function uniqueId(): string {\n return `${baseId}-${lastId++}`\n}\n\nexport function getOwnProperty<T = unknown>(object: Record<string, T>, property: string): T | undefined {\n // Checks if `hasOwn` method is defined avoiding errors with older Node.js versions\n if (Object.hasOwn === undefined) {\n return Object.prototype.hasOwnProperty.call(object, property) ? object[property] : undefined\n }\n\n return Object.hasOwn(object, property) ? object[property] : undefined\n}\n\nexport function getTokenFrequency(token: string, tokens: string[]): number {\n let count = 0\n\n for (const t of tokens) {\n if (t === token) {\n count++\n }\n }\n\n return count\n}\n\nexport function insertSortedValue(\n arr: TokenScore[],\n el: TokenScore,\n compareFn = sortTokenScorePredicate\n): TokenScore[] {\n let low = 0\n let high = arr.length\n let mid\n\n while (low < high) {\n mid = (low + high) >>> 1\n if (compareFn(el, arr[mid]) < 0) {\n high = mid\n } else {\n low = mid + 1\n }\n }\n\n arr.splice(low, 0, el)\n\n return arr\n}\n\nexport function sortTokenScorePredicate(a: TokenScore, b: TokenScore): number {\n if (b[1] === a[1]) {\n return a[0] - b[0]\n }\n\n return b[1] - a[1]\n}\n\n// Intersection function taken from https://github.com/lovasoa/fast_array_intersect.\n// MIT Licensed at the time of writing.\nexport function intersect<T>(arrays: Array<readonly T[]>): T[] {\n if (arrays.length === 0) {\n return []\n } else if (arrays.length === 1) {\n return arrays[0] as T[]\n }\n\n for (let i = 1; i < arrays.length; i++) {\n if (arrays[i].length < arrays[0].length) {\n const tmp = arrays[0]\n arrays[0] = arrays[i]\n arrays[i] = tmp\n }\n }\n\n const set = new Map()\n for (const elem of arrays[0]) {\n set.set(elem, 1)\n }\n for (let i = 1; i < arrays.length; i++) {\n let found = 0\n for (const elem of arrays[i]) {\n const count = set.get(elem)\n if (count === i) {\n set.set(elem, count + 1)\n found++\n }\n }\n if (found === 0) return []\n }\n\n return arrays[0].filter((e) => {\n const count = set.get(e)\n if (count !== undefined) set.set(e, 0)\n return count === arrays.length\n })\n}\n\nexport function getDocumentProperties(doc: AnyDocument, paths: string[]): Record<string, SearchableValue> {\n const properties: Record<string, SearchableValue> = {}\n\n const pathsLength = paths.length\n for (let i = 0; i < pathsLength; i++) {\n const path = paths[i]\n const pathTokens = path.split('.')\n\n let current: SearchableValue | AnyDocument | undefined = doc\n const pathTokensLength = pathTokens.length\n for (let j = 0; j < pathTokensLength; j++) {\n current = current[pathTokens[j]!]\n\n // We found an object but we were supposed to be done\n if (typeof current === 'object') {\n if (\n current !== null &&\n 'lat' in current &&\n 'lon' in current &&\n typeof current.lat === 'number' &&\n typeof current.lon === 'number'\n ) {\n current = properties[path] = current as SearchableValue\n break\n } else if (!Array.isArray(current) && current !== null && j === pathTokensLength - 1) {\n current = undefined\n break\n }\n } else if ((current === null || typeof current !== 'object') && j < pathTokensLength - 1) {\n // We can't recurse anymore but we were supposed to\n current = undefined\n break\n }\n }\n\n if (typeof current !== 'undefined') {\n properties[path] = current as SearchableValue\n }\n }\n\n return properties\n}\n\nexport function getNested<T = SearchableValue>(obj: object, path: string): Optional<T> {\n const props = getDocumentProperties(obj as AnyDocument, [path])\n\n return props[path] as T | undefined\n}\n\nexport function flattenObject(obj: object, prefix = ''): AnyDocument {\n const result: AnyDocument = {}\n\n for (const key in obj) {\n const prop = `${prefix}${key}`\n const objKey = (obj as AnyDocument)[key]\n\n if (typeof objKey === 'object' && objKey !== null) {\n Object.assign(result, flattenObject(objKey, `${prop}.`))\n } else {\n result[prop] = objKey\n }\n }\n return result\n}\n\nconst mapDistanceToMeters = {\n cm: 0.01,\n m: 1,\n km: 1000,\n ft: 0.3048,\n yd: 0.9144,\n mi: 1609.344\n}\n\nexport function convertDistanceToMeters(distance: number, unit: GeosearchDistanceUnit): number {\n const ratio = mapDistanceToMeters[unit]\n\n if (ratio === undefined) {\n throw new Error(createError('INVALID_DISTANCE_SUFFIX', distance).message)\n }\n\n return distance * ratio\n}\n\nexport function removeVectorsFromHits(searchResult: Results<AnyDocument>, vectorProperties: string[]): void {\n searchResult.hits = searchResult.hits.map((result) => ({\n ...result,\n document: {\n ...result.document,\n // Remove embeddings from the result\n ...vectorProperties.reduce((acc, prop) => {\n const path = prop.split('.')\n const lastKey = path.pop()!\n let obj = acc\n for (const key of path) {\n obj[key] = obj[key] ?? {}\n obj = obj[key] as any\n }\n obj[lastKey] = null\n return acc\n }, result.document)\n }\n }))\n}\n\nexport function isPromise(obj: any): obj is Promise<unknown> {\n return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'\n}\n\nexport function isAsyncFunction(func: any): boolean {\n return func?.constructor?.name === 'AsyncFunction'\n}\n\n\nconst withIntersection = 'intersection' in (new Set());\nexport function setIntersection<V>(...sets: Set<V>[]): Set<V> {\n // Fast path 1\n if (sets.length === 0) {\n return new Set();\n }\n // Fast path 2\n if (sets.length === 1) {\n return sets[0];\n }\n // Fast path 3\n if (sets.length === 2) {\n const set1 = sets[0];\n const set2 = sets[1];\n\n if (withIntersection) {\n return set1.intersection(set2);\n }\n const result = new Set<V>();\n const base = set1.size < set2.size ? set1 : set2;\n const other = base === set1 ? set2 : set1;\n for (const value of base) {\n if (other.has(value)) {\n result.add(value);\n }\n }\n return result;\n }\n\n // Slow path\n // Find the smallest set\n const min = {\n index: 0,\n size: sets[0].size,\n }\n for (let i = 1; i < sets.length; i++) {\n if (sets[i].size < min.size) {\n min.index = i;\n min.size = sets[i].size;\n }\n }\n\n if (withIntersection) {\n let base = sets[min.index];\n for (let i = 0; i < sets.length; i++) {\n if (i === min.index) {\n continue;\n }\n base = base.intersection(sets[i]);\n }\n\n return base;\n }\n\n // manual implementation:\n // intersect all sets with the smallest set\n const base = sets[min.index];\n for (let i = 0; i < sets.length; i++) {\n if (i === min.index) {\n continue;\n }\n const other = sets[i];\n for (const value of base) {\n if (!other.has(value)) {\n base.delete(value);\n }\n }\n }\n\n return base;\n}\n\nconst withUnion = 'union' in (new Set());\nexport function setUnion<V>(set1: Set<V> | undefined, set2: Set<V>) {\n if (withUnion) {\n if (set1) {\n return set1.union(set2);\n }\n return set2;\n }\n\n if (!set1) {\n return new Set(set2);\n }\n return new Set([...set1, ...set2]);\n}\n","import { SUPPORTED_LANGUAGES } from './components/tokenizer/languages.js'\nimport { sprintf } from './utils.js'\n\nconst allLanguages = SUPPORTED_LANGUAGES.join('\\n - ')\n\nconst errors = {\n NO_LANGUAGE_WITH_CUSTOM_TOKENIZER: 'Do not pass the language option to create when using a custom tokenizer.',\n LANGUAGE_NOT_SUPPORTED: `Language \"%s\" is not supported.\\nSupported languages are:\\n - ${allLanguages}`,\n INVALID_STEMMER_FUNCTION_TYPE: `config.stemmer property must be a function.`,\n MISSING_STEMMER: `As of version 1.0.0 @orama/orama does not ship non English stemmers by default. To solve this, please explicitly import and specify the \"%s\" stemmer from the package @orama/stemmers. See https://docs.oramasearch.com/open-source/text-analysis/stemming for more information.`,\n CUSTOM_STOP_WORDS_MUST_BE_FUNCTION_OR_ARRAY: 'Custom stop words array must only contain strings.',\n UNSUPPORTED_COMPONENT: `Unsupported component \"%s\".`,\n COMPONENT_MUST_BE_FUNCTION: `The component \"%s\" must be a function.`,\n COMPONENT_MUST_BE_FUNCTION_OR_ARRAY_FUNCTIONS: `The component \"%s\" must be a function or an array of functions.`,\n INVALID_SCHEMA_TYPE: `Unsupported schema type \"%s\" at \"%s\". Expected \"string\", \"boolean\" or \"number\" or array of them.`,\n DOCUMENT_ID_MUST_BE_STRING: `Document id must be of type \"string\". Got \"%s\" instead.`,\n DOCUMENT_ALREADY_EXISTS: `A document with id \"%s\" already exists.`,\n DOCUMENT_DOES_NOT_EXIST: `A document with id \"%s\" does not exists.`,\n MISSING_DOCUMENT_PROPERTY: `Missing searchable property \"%s\".`,\n INVALID_DOCUMENT_PROPERTY: `Invalid document property \"%s\": expected \"%s\", got \"%s\"`,\n UNKNOWN_INDEX: `Invalid property name \"%s\". Expected a wildcard string (\"*\") or array containing one of the following properties: %s`,\n INVALID_BOOST_VALUE: `Boost value must be a number greater than, or less than 0.`,\n INVALID_FILTER_OPERATION: `You can only use one operation per filter, you requested %d.`,\n SCHEMA_VALIDATION_FAILURE: `Cannot insert document due schema validation failure on \"%s\" property.`,\n INVALID_SORT_SCHEMA_TYPE: `Unsupported sort schema type \"%s\" at \"%s\". Expected \"string\" or \"number\".`,\n CANNOT_SORT_BY_ARRAY: `Cannot configure sort for \"%s\" because it is an array (%s).`,\n UNABLE_TO_SORT_ON_UNKNOWN_FIELD: `Unable to sort on unknown field \"%s\". Allowed fields: %s`,\n SORT_DISABLED: `Sort is disabled. Please read the documentation at https://docs.oramasearch for more information.`,\n UNKNOWN_GROUP_BY_PROPERTY: `Unknown groupBy property \"%s\".`,\n INVALID_GROUP_BY_PROPERTY: `Invalid groupBy property \"%s\". Allowed types: \"%s\", but given \"%s\".`,\n UNKNOWN_FILTER_PROPERTY: `Unknown filter property \"%s\".`,\n INVALID_VECTOR_SIZE: `Vector size must be a number greater than 0. Got \"%s\" instead.`,\n INVALID_VECTOR_VALUE: `Vector value must be a number greater than 0. Got \"%s\" instead.`,\n INVALID_INPUT_VECTOR: `Property \"%s\" was declared as a %s-dimensional vector, but got a %s-dimensional vector instead.\\nInput vectors must be of the size declared in the schema, as calculating similarity between vectors of different sizes can lead to unexpected results.`,\n WRONG_SEARCH_PROPERTY_TYPE: `Property \"%s\" is not searchable. Only \"string\" properties are searchable.`,\n FACET_NOT_SUPPORTED: `Facet doens't support the type \"%s\".`,\n INVALID_DISTANCE_SUFFIX: `Invalid distance suffix \"%s\". Valid suffixes are: cm, m, km, mi, yd, ft.`,\n INVALID_SEARCH_MODE: `Invalid search mode \"%s\". Valid modes are: \"fulltext\", \"vector\", \"hybrid\".`,\n MISSING_VECTOR_AND_SECURE_PROXY: `No vector was provided and no secure proxy was configured. Please provide a vector or configure an Orama Secure Proxy to perform hybrid search.`,\n MISSING_TERM: `\"term\" is a required parameter when performing hybrid search. Please provide a search term.`,\n INVALID_VECTOR_INPUT: `Invalid \"vector\" property. Expected an object with \"value\" and \"property\" properties, but got \"%s\" instead.`,\n PLUGIN_CRASHED: `A plugin crashed during initialization. Please check the error message for more information:`,\n PLUGIN_SECURE_PROXY_NOT_FOUND: `Could not find '@orama/secure-proxy-plugin' installed in your Orama instance.\\nPlease install it before proceeding with creating an answer session.\\nRead more at https://docs.orama.com/open-source/plugins/plugin-secure-proxy\\n`,\n PLUGIN_SECURE_PROXY_MISSING_CHAT_MODEL: `Could not find a chat model defined in the secure proxy plugin configuration.\\nPlease provide a chat model before proceeding with creating an answer session.\\nRead more at https://docs.orama.com/open-source/plugins/plugin-secure-proxy\\n`,\n ANSWER_SESSION_LAST_MESSAGE_IS_NOT_ASSISTANT: `The last message in the session is not an assistant message. Cannot regenerate non-assistant messages.`,\n PLUGIN_COMPONENT_CONFLICT: `The component \"%s\" is already defined. The plugin \"%s\" is trying to redefine it.`,\n}\n\nexport type ErrorCode = keyof typeof errors\n\nexport interface OramaError extends Error {\n code: string\n}\n\nexport function createError(code: ErrorCode, ...args: Array<string | number>): OramaError {\n const error = new Error(sprintf(errors[code] ?? `Unsupported Orama Error code: ${code}`, ...args)) as OramaError\n error.code = code\n if ('captureStackTrace' in Error.prototype) {\n Error.captureStackTrace(error)\n }\n\n return error\n}\n","import type { Optional } from '../types.js'\nimport { createError } from '../errors.js'\nimport { Point } from '../trees/bkd.js'\nimport {\n AnyDocument,\n AnyOrama,\n ArraySearchableType,\n ElapsedTime,\n ScalarSearchableType,\n SearchableType,\n TypedDocument,\n Vector\n} from '../types.js'\nimport { formatNanoseconds, uniqueId } from '../utils.js'\n\nexport { getDocumentProperties } from '../utils.js'\n\nexport function formatElapsedTime(n: bigint): ElapsedTime {\n return {\n raw: Number(n),\n formatted: formatNanoseconds(n)\n }\n}\n\nexport function getDocumentIndexId(doc: AnyDocument): string {\n if (doc.id) {\n if (typeof doc.id !== 'string') {\n throw createError('DOCUMENT_ID_MUST_BE_STRING', typeof doc.id)\n }\n\n return doc.id\n }\n\n return uniqueId()\n}\n\nexport function validateSchema<T extends AnyOrama, ResultDocument extends TypedDocument<T>>(\n doc: ResultDocument,\n schema: T['schema']\n): Optional<string> {\n for (const [prop, type] of Object.entries(schema)) {\n const value = doc[prop]\n\n if (typeof value === 'undefined') {\n continue\n }\n\n if (\n type === 'geopoint' &&\n typeof value === 'object' &&\n typeof value.lon === 'number' &&\n typeof value.lat === 'number'\n ) {\n continue\n }\n\n if (type === 'enum' && (typeof value === 'string' || typeof value === 'number')) {\n continue\n }\n if (type === 'enum[]' && Array.isArray(value)) {\n const valueLength = value.length\n for (let i = 0; i < valueLength; i++) {\n if (typeof value[i] !== 'string' && typeof value[i] !== 'number') {\n return prop + '.' + i\n }\n }\n continue\n }\n\n if (isVectorType(type)) {\n const vectorSize = getVectorSize(type)\n if (!Array.isArray(value) || value.length !== vectorSize) {\n throw createError('INVALID_INPUT_VECTOR', prop, vectorSize, value.length)\n }\n continue\n }\n\n if (isArrayType(type)) {\n if (!Array.isArray(value)) {\n return prop\n }\n const expectedType = getInnerType(type)\n\n const valueLength = value.length\n for (let i = 0; i < valueLength; i++) {\n if (typeof value[i] !== expectedType) {\n return prop + '.' + i\n }\n }\n\n continue\n }\n\n if (typeof type === 'object') {\n if (!value || typeof value !== 'object') {\n return prop\n }\n\n // using as ResultDocument is not exactly right but trying to be type-safe here is not useful\n const subProp = validateSchema(value as ResultDocument, type)\n if (subProp) {\n return prop + '.' + subProp\n }\n continue\n }\n\n if (typeof value !== type) {\n return prop\n }\n }\n\n return undefined\n}\n\nconst IS_ARRAY_TYPE: Record<SearchableType, boolean> = {\n string: false,\n number: false,\n boolean: false,\n enum: false,\n geopoint: false,\n 'string[]': true,\n 'number[]': true,\n 'boolean[]': true,\n 'enum[]': true\n}\n\nconst INNER_TYPE: Record<ArraySearchableType, ScalarSearchableType> = {\n 'string[]': 'string',\n 'number[]': 'number',\n 'boolean[]': 'boolean',\n 'enum[]': 'enum'\n}\n\nexport function isGeoPointType(type: unknown): type is Point {\n return type === 'geopoint'\n}\n\nexport function isVectorType(type: unknown): type is Vector {\n return typeof type === 'string' && /^vector\\[\\d+\\]$/.test(type)\n}\n\nexport function isArrayType(type: unknown): type is ArraySearchableType {\n return typeof type === 'string' && IS_ARRAY_TYPE[type]\n}\n\nexport function getInnerType(type: ArraySearchableType): ScalarSearchableType {\n return INNER_TYPE[type]\n}\n\nexport function getVectorSize(type: string): number {\n const size = Number(type.slice(7, -1))\n\n switch (true) {\n case isNaN(size):\n throw createError('INVALID_VECTOR_VALUE', type)\n case size <= 0:\n throw createError('INVALID_VECTOR_SIZE', type)\n default:\n return size\n }\n}\n","import { AnyOrama } from '../types.js'\n\nexport type DocumentID = string | number\nexport type InternalDocumentID = number\n\nexport type InternalDocumentIDStore = {\n idToInternalId: Map<string, number>\n internalIdToId: string[]\n save: (store: InternalDocumentIDStore) => unknown\n load: <T extends AnyOrama>(orama: T, raw: unknown) => void\n}\n\nexport function createInternalDocumentIDStore(): InternalDocumentIDStore {\n return {\n idToInternalId: new Map(),\n internalIdToId: [],\n save,\n load\n }\n}\n\nexport function save(store: InternalDocumentIDStore): unknown {\n return {\n internalIdToId: store.internalIdToId\n }\n}\n\nexport function load<T extends AnyOrama>(orama: T, raw: unknown): void {\n const { internalIdToId } = raw as InternalDocumentIDStore\n\n orama.internalDocumentIDStore.idToInternalId.clear()\n orama.internalDocumentIDStore.internalIdToId = []\n const internalIdToIdLength = internalIdToId.length\n\n for (let i = 0; i < internalIdToIdLength; i++) {\n const internalIdItem = internalIdToId[i]\n orama.internalDocumentIDStore.idToInternalId.set(internalIdItem, i + 1)\n orama.internalDocumentIDStore.internalIdToId.push(internalIdItem)\n }\n}\n\nexport function getInternalDocumentId(store: InternalDocumentIDStore, id: DocumentID): InternalDocumentID {\n if (typeof id === 'string') {\n const internalId = store.idToInternalId.get(id)\n\n if (internalId) {\n return internalId\n }\n\n const currentId = store.idToInternalId.size + 1\n\n store.idToInternalId.set(id, currentId)\n store.internalIdToId.push(id)\n\n return currentId\n }\n\n if (id > store.internalIdToId.length) {\n return getInternalDocumentId(store, id.toString())\n }\n\n return id\n}\n\nexport function getDocumentIdFromInternalId(store: InternalDocumentIDStore, internalId: InternalDocumentID): string {\n if (store.internalIdToId.length < internalId) {\n throw new Error(`Invalid internalId ${internalId}`)\n }\n\n return store.internalIdToId[internalId - 1]\n}\n","import type {\n AnyIndexStore,\n AnyOrama,\n ArraySearchableType,\n BM25Params,\n ComparisonOperator,\n EnumArrComparisonOperator,\n EnumComparisonOperator,\n GeosearchOperation,\n GeosearchPolygonOperator,\n GeosearchRadiusOperator,\n IIndex,\n ScalarSearchableType,\n SearchableType,\n SearchableValue,\n Tokenizer,\n TokenScore,\n WhereCondition\n} from '../types.js'\nimport type { InsertOptions } from '../methods/insert.js'\nimport type { Point as BKDGeoPoint } from '../trees/bkd.js'\nimport { FindResult, RadixNode } from '../trees/radix.js'\nimport { createError } from '../errors.js'\nimport { AVLTree } from '../trees/avl.js'\nimport { FlatTree } from '../trees/flat.js'\nimport { RadixTree } from '../trees/radix.js'\nimport { BKDTree } from '../trees/bkd.js'\nimport { BoolNode } from '../trees/bool.js'\n\nimport { convertDistanceToMeters, setIntersection, setUnion } from '../utils.js'\nimport { BM25 } from './algorithms.js'\nimport { getInnerType, getVectorSize, isArrayType, isVectorType } from './defaults.js'\nimport {\n DocumentID,\n getInternalDocumentId,\n InternalDocumentID,\n InternalDocumentIDStore\n} from './internal-document-id-store.js'\nimport { VectorIndex, VectorType } from '../trees/vector.js'\n\nexport type FrequencyMap = {\n [property: string]: {\n [documentID: InternalDocumentID]:\n | {\n [token: string]: number\n }\n | undefined\n }\n}\n\nexport type TreeType = 'AVL' | 'Radix' | 'Bool' | 'Flat' | 'BKD'\n\nexport type TTree<T = TreeType, N = unknown> = {\n type: T\n node: N\n isArray: boolean\n}\n\nexport type Tree =\n | TTree<'Radix', RadixNode>\n | TTree<'AVL', AVLTree<number, InternalDocumentID>>\n | TTree<'Bool', BoolNode<InternalDocumentID>>\n | TTree<'Flat', FlatTree>\n | TTree<'BKD', BKDTree>\n\nexport interface Index extends AnyIndexStore {\n sharedInternalDocumentStore: InternalDocumentIDStore\n indexes: Record<string, Tree>\n // vectorIndexes: Record<string, TTree<'Vector', VectorIndex>>\n searchableProperties: string[]\n searchablePropertiesWithTypes: Record<string, SearchableType>\n frequencies: FrequencyMap\n tokenOccurrences: Record<string, Record<string, number>>\n avgFieldLength: Record<string, number>\n fieldLengths: Record<string, Record<InternalDocumentID, number | undefined>>\n}\n\nexport function insertDocumentScoreParameters(\n index: Index,\n prop: string,\n id: DocumentID,\n tokens: string[],\n docsCount: number\n): void {\n const internalId = getInternalDocumentId(index.sharedInternalDocumentStore, id)\n\n index.avgFieldLength[prop] = ((index.avgFieldLength[prop] ?? 0) * (docsCount - 1) + tokens.length) / docsCount\n index.fieldLengths[prop][internalId] = tokens.length\n index.frequencies[prop][internalId] = {}\n}\n\nexport function insertTokenScoreParameters(\n index: Index,\n prop: string,\n id: DocumentID,\n tokens: string[],\n token: string\n): void {\n let tokenFrequency = 0\n\n for (const t of tokens) {\n if (t === token) {\n tokenFrequency++\n }\n }\n\n const internalId = getInternalDocumentId(index.sharedInternalDocumentStore, id)\n const tf = tokenFrequency / tokens.length\n\n index.frequencies[prop][internalId]![token] = tf\n\n if (!(token in index.tokenOccurrences[prop])) {\n index.tokenOccurrences[prop][token] = 0\n }\n\n // increase a token counter that may not yet exist\n index.tokenOccurrences[prop][token] = (index.tokenOccurrences[prop][token] ?? 0) + 1\n}\n\nexport function removeDocumentScoreParameters(index: Index, prop: string, id: DocumentID, docsCount: number): void {\n const internalId = getInternalDocumentId(index.sharedInternalDocumentStore, id)\n\n if (docsCount > 1) {\n index.avgFieldLength[prop] =\n (index.avgFieldLength[prop] * docsCount - index.fieldLengths[prop][internalId]!) / (docsCount - 1)\n } else {\n index.avgFieldLength[prop] = undefined as unknown as number\n }\n index.fieldLengths[prop][internalId] = undefined\n index.frequencies[prop][internalId] = undefined\n}\n\nexport function removeTokenScoreParameters(index: Index, prop: string, token: string): void {\n index.tokenOccurrences[prop][token]--\n}\n\nexport function create<T extends AnyOrama, TSchema extends T['schema']>(\n orama: T,\n sharedInternalDocumentStore: T['internalDocumentIDStore'],\n schema: TSchema,\n index?: Index,\n prefix = ''\n): Index {\n if (!index) {\n index = {\n sharedInternalDocumentStore,\n indexes: {},\n vectorIndexes: {},\n searchableProperties: [],\n searchablePropertiesWithTypes: {},\n frequencies: {},\n tokenOccurrences: {},\n avgFieldLength: {},\n fieldLengths: {}\n }\n }\n\n for (const [prop, type] of Object.entries<SearchableType>(schema)) {\n const path = `${prefix}${prefix ? '.' : ''}${prop}`\n\n if (typeof type === 'object' && !Array.isArray(type)) {\n // Nested\n create(orama, sharedInternalDocumentStore, type, index, path)\n continue\n }\n\n if (isVectorType(type)) {\n index.searchableProperties.push(path)\n index.searchablePropertiesWithTypes[path] = type\n index.vectorIndexes[path] = {\n type: 'Vector',\n node: new VectorIndex(getVectorSize(type)),\n isArray: false,\n }\n } else {\n const isArray = /\\[/.test(type as string)\n switch (type) {\n case 'boolean':\n case 'boolean[]':\n index.indexes[path] = { type: 'Bool', node: new BoolNode(), isArray }\n break\n case 'number':\n case 'number[]':\n index.indexes[path] = { type: 'AVL', node: new AVLTree<number, InternalDocumentID>(0, []), isArray }\n break\n case 'string':\n case 'string[]':\n index.indexes[path] = { type: 'Radix', node: new RadixTree(), isArray }\n index.avgFieldLength[path] = 0\n index.frequencies[path] = {}\n index.tokenOccurrences[path] = {}\n index.fieldLengths[path] = {}\n break\n case 'enum':\n case 'enum[]':\n index.indexes[path] = { type: 'Flat', node: new FlatTree(), isArray }\n break\n case 'geopoint':\n index.indexes[path] = { type: 'BKD', node: new BKDTree(), isArray }\n break\n default:\n throw createError('INVALID_SCHEMA_TYPE', Array.isArray(type) ? 'array' : type, path)\n }\n\n index.searchableProperties.push(path)\n index.searchablePropertiesWithTypes[path] = type\n }\n }\n\n return index\n}\n\nfunction insertScalarBuilder(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n internalId: InternalDocumentID,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number,\n options?: InsertOptions\n) {\n return (value: SearchableValue) => {\n const { type, node } = index.indexes[prop]\n switch (type) {\n case 'Bool': {\n node[value ? 'true' : 'false'].add(internalId)\n break\n }\n case 'AVL': {\n const avlRebalanceThreshold = options?.avlRebalanceThreshold ?? 1\n node.insert(value as number, internalId, avlRebalanceThreshold)\n break\n }\n case 'Radix': {\n const tokens = tokenizer.tokenize(value as string, language, prop, false)\n implementation.insertDocumentScoreParameters(index, prop, internalId, tokens, docsCount)\n\n for (const token of tokens) {\n implementation.insertTokenScoreParameters(index, prop, internalId, tokens, token)\n\n node.insert(token, internalId)\n }\n\n break\n }\n case 'Flat': {\n node.insert(value as ScalarSearchableType, internalId)\n break\n }\n case 'BKD': {\n node.insert(value as unknown as BKDGeoPoint, [internalId])\n break\n }\n }\n }\n}\n\nexport function insert(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number,\n options?: InsertOptions\n): void {\n if (isVectorType(schemaType)) {\n return insertVector(index, prop, value as number[] | Float32Array, id, internalId)\n }\n\n const insertScalar = insertScalarBuilder(implementation, index, prop, internalId, language, tokenizer, docsCount, options)\n\n if (!isArrayType(schemaType)) {\n return insertScalar(value)\n }\n\n const elements = value as Array<string | number | boolean>\n const elementsLength = elements.length\n for (let i = 0; i < elementsLength; i++) {\n insertScalar(elements[i])\n }\n}\n\nexport function insertVector(index: AnyIndexStore, prop: string, value: number[] | VectorType, id: DocumentID, internalDocumentId: InternalDocumentID): void {\n index.vectorIndexes[prop].node.add(internalDocumentId, value)\n}\n\nfunction removeScalar(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: ScalarSearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n): boolean {\n if (isVectorType(schemaType)) {\n index.vectorIndexes[prop].node.remove(internalId)\n return true\n }\n\n const { type, node } = index.indexes[prop]\n switch (type) {\n case 'AVL': {\n node.removeDocument(value as number, internalId)\n return true\n }\n case 'Bool': {\n node[value ? 'true' : 'false'].delete(internalId)\n return true\n }\n case 'Radix': {\n const tokens = tokenizer.tokenize(value as string, language, prop)\n\n implementation.removeDocumentScoreParameters(index, prop, id, docsCount)\n\n for (const token of tokens) {\n implementation.removeTokenScoreParameters(index, prop, token)\n node.removeDocumentByWord(token, internalId)\n }\n\n return true\n }\n case 'Flat': {\n node.removeDocument(internalId, value as ScalarSearchableType)\n return true\n }\n case 'BKD': {\n node.removeDocByID(value as unknown as BKDGeoPoint, internalId)\n return false\n }\n }\n}\n\nexport function remove(\n implementation: IIndex<Index>,\n index: Index,\n prop: string,\n id: DocumentID,\n internalId: InternalDocumentID,\n value: SearchableValue,\n schemaType: SearchableType,\n language: string | undefined,\n tokenizer: Tokenizer,\n docsCount: number\n): boolean {\n if (!isArrayType(schemaType)) {\n return removeScalar(\n implementation,\n index,\n prop,\n id,\n internalId,\n value,\n schemaType as ScalarSearchableType,\n language,\n tokenizer,\n docsCount\n )\n }\n\n const innerSchemaType = getInnerType(schemaType as ArraySearchableType)\n\n const elements = value as Array<string | number | boolean>\n const elementsLength = elements.length\n for (let i = 0; i < elementsLength; i++) {\n removeScalar(implementation, index, prop, id, internalId, elements[i], innerSchemaType, language, tokenizer, docsCount)\n }\n\n return true\n}\n\nexport function calculateResultScores(\n index: Index,\n prop: string,\n term: string,\n ids: InternalDocumentID[],\n docsCount: number,\n bm25Relevance: Required<BM25Params>,\n resultsMap: Map<number, number>,\n boostPerProperty: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined\n) {\n const documentIDs = Array.from(ids)\n\n // Exact fields for TF-IDF\n const avgFieldLength = index.avgFieldLength[prop]\n const fieldLengths = index.fieldLengths[prop]\n const oramaOccurrences = index.tokenOccurrences[prop]\n const oramaFrequencies = index.frequencies[prop]\n\n // oramaOccurrences[term] can be undefined, 0, string, or { [k: string]: number }\n const termOccurrences = typeof oramaOccurrences[term] === 'number' ? oramaOccurrences[term] ?? 0 : 0\n\n // Calculate TF-IDF value for each term, in each document, for each index.\n const documentIDsLength = documentIDs.length\n for (let k = 0; k < documentIDsLength; k++) {\n const internalId = documentIDs[k]\n if (whereFiltersIDs && !whereFiltersIDs.has(internalId)) {\n continue\n }\n\n const tf = oramaFrequencies?.[internalId]?.[term] ?? 0\n\n const bm25 = BM25(\n tf,\n termOccurrences,\n docsCount,\n fieldLengths[internalId]!,\n avgFieldLength,\n bm25Relevance,\n )\n\n if (resultsMap.has(internalId)) {\n resultsMap.set(internalId, resultsMap.get(internalId)! + bm25 * boostPerProperty)\n } else {\n resultsMap.set(internalId, bm25 * boostPerProperty)\n }\n }\n}\n\nfunction searchInProperty(\n index: Index,\n tree: RadixTree,\n prop: string,\n tokens: string[],\n exact: boolean,\n tolerance: number,\n resultsMap: Map<number, number>,\n boostPerProperty: number,\n bm25Relevance: Required<BM25Params>,\n docsCount: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined\n) {\n const tokenLength = tokens.length;\n for (let i = 0; i < tokenLength; i++) {\n const term = tokens[i];\n\n const searchResult = tree.find({ term, exact, tolerance })\n\n const termsFound = Object.keys(searchResult)\n const termsFoundLength = termsFound.length;\n for (let j = 0; j < termsFoundLength; j++) {\n const word = termsFound[j]\n const ids = searchResult[word]\n calculateResultScores(\n index,\n prop,\n word,\n ids,\n docsCount,\n bm25Relevance,\n resultsMap,\n boostPerProperty,\n whereFiltersIDs,\n )\n }\n }\n}\n\nexport function search(\n index: Index,\n term: string,\n tokenizer: Tokenizer,\n language: string | undefined,\n propertiesToSearch: string[],\n exact: boolean,\n tolerance: number,\n boost: Record<string, number>,\n relevance: Required<BM25Params>,\n docsCount: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined,\n): TokenScore[] {\n const tokens = tokenizer.tokenize(term, language)\n\n const resultsMap = new Map<number, number>()\n for (const prop of propertiesToSearch) {\n if (!(prop in index.indexes)) {\n continue\n }\n\n const tree = index.indexes[prop]\n const { type } = tree\n if (type !== 'Radix') {\n throw createError('WRONG_SEARCH_PROPERTY_TYPE', prop)\n }\n const boostPerProperty = boost[prop] ?? 1\n if (boostPerProperty <= 0) {\n throw createError('INVALID_BOOST_VALUE', boostPerProperty)\n }\n\n // if the tokenizer returns an empty array, we returns all the documents\n if (tokens.length === 0 && !term) {\n tokens.push('')\n }\n\n searchInProperty(\n index,\n tree.node,\n prop,\n tokens,\n exact,\n tolerance,\n resultsMap,\n boostPerProperty,\n relevance,\n docsCount,\n whereFiltersIDs,\n )\n }\n\n return Array.from(resultsMap)\n}\n\nexport function searchByWhereClause<T extends AnyOrama>(\n index: Index,\n tokenizer: Tokenizer,\n filters: Partial<WhereCondition<T['schema']>>,\n language: string | undefined\n): Set<InternalDocumentID> {\n const filterKeys = Object.keys(filters)\n\n const filtersMap: Record<string, Set<InternalDocumentID>> = filterKeys.reduce(\n (acc, key) => ({\n [key]: new Set(),\n ...acc\n }),\n {}\n )\n\n for (const param of filterKeys) {\n const operation = filters[param]!\n\n if (typeof index.indexes[param] === 'undefined') {\n throw createError('UNKNOWN_FILTER_PROPERTY', param)\n }\n\n const { node, type, isArray } = index.indexes[param]\n\n if (type === 'Bool') {\n const idx = node\n const filteredIDs = operation ? idx.true : idx.false\n filtersMap[param] = setUnion(filtersMap[param], filteredIDs)\n continue\n }\n\n if (type === 'BKD') {\n let reqOperation: 'radius' | 'polygon'\n\n if ('radius' in (operation as GeosearchOperation)) {\n reqOperation = 'radius'\n } else if ('polygon' in (operation as GeosearchOperation)) {\n reqOperation = 'polygon'\n } else {\n throw new Error(`Invalid operation ${operation}`)\n }\n\n if (reqOperation === 'radius') {\n const {\n value,\n coordinates,\n unit = 'm',\n inside = true,\n highPrecision = false\n } = operation[reqOperation] as GeosearchRadiusOperator['radius']\n const distanceInMeters = convertDistanceToMeters(value, unit)\n const ids = node.searchByRadius(coordinates as BKDGeoPoint, distanceInMeters, inside, undefined, highPrecision)\n filtersMap[param] = addGeoResult(filtersMap[param], ids)\n } else {\n const {\n coordinates,\n inside = true,\n highPrecision = false\n } = operation[reqOperation] as GeosearchPolygonOperator['polygon']\n const ids = node.searchByPolygon(coordinates as BKDGeoPoint[], inside, undefined, highPrecision)\n filtersMap[param] = addGeoResult(filtersMap[param], ids)\n }\n\n continue\n }\n\n if (type === 'Radix' && (typeof operation === 'string' || Array.isArray(operation))) {\n for (const raw of [operation].flat()) {\n const term = tokenizer.tokenize(raw, language, param)\n for (const t of term) {\n const filteredIDsResults = node.find({ term: t, exact: true })\n filtersMap[param] = addFindResult(filtersMap[param], filteredIDsResults)\n }\n }\n\n continue\n }\n\n const operationKeys = Object.keys(operation)\n\n if (operationKeys.length > 1) {\n throw createError('INVALID_FILTER_OPERATION', operationKeys.length)\n }\n\n if (type === 'Flat') {\n const results = new Set(isArray\n ? node.filterArr(operation as EnumArrComparisonOperator)\n : node.filter(operation as EnumComparisonOperator))\n\n filtersMap[param] = setUnion(filtersMap[param], results)\n\n continue\n }\n\n if (type === 'AVL') {\n const operationOpt = operationKeys[0] as keyof ComparisonOperator\n const operationValue = (operation as ComparisonOperator)[operationOpt]\n let filteredIDs: Set<InternalDocumentID> \n\n switch (operationOpt) {\n case 'gt': {\n filteredIDs = node.greaterThan(operationValue as number, false)\n break\n }\n case 'gte': {\n filteredIDs = node.greaterThan(operationValue as number, true)\n break\n }\n case 'lt': {\n filteredIDs = node.lessThan(operationValue as number, false)\n break\n }\n case 'lte': {\n filteredIDs = node.lessThan(operationValue as number, true)\n break\n }\n case 'eq': {\n const ret = node.find(operationValue as number)\n filteredIDs = ret ?? new Set()\n break\n }\n case 'between': {\n const [min, max] = operationValue as number[]\n filteredIDs = node.rangeSearch(min, max)\n break\n }\n default:\n throw createError('INVALID_FILTER_OPERATION', operationOpt)\n }\n\n filtersMap[param] = setUnion(filtersMap[param], filteredIDs)\n }\n }\n\n // AND operation: calculate the intersection between all the IDs in filterMap\n return setIntersection(...Object.values(filtersMap))\n}\n\nexport function getSearchableProperties(index: Index): string[] {\n return index.searchableProperties\n}\n\nexport function getSearchablePropertiesWithTypes(index: Index): Record<string, SearchableType> {\n return index.searchablePropertiesWithTypes\n}\n\nexport function load<R = unknown>(sharedInternalDocumentStore: InternalDocumentIDStore, raw: R): Index {\n const {\n indexes: rawIndexes,\n vectorIndexes: rawVectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n } = raw as Index\n\n const indexes: Index['indexes'] = {}\n const vectorIndexes: Index['vectorIndexes'] = {}\n\n for (const prop of Object.keys(rawIndexes)) {\n const { node, type, isArray } = rawIndexes[prop]\n\n switch (type) {\n case 'Radix':\n indexes[prop] = {\n type: 'Radix',\n node: RadixTree.fromJSON(node),\n isArray\n }\n break\n case 'Flat':\n indexes[prop] = {\n type: 'Flat',\n node: FlatTree.fromJSON(node),\n isArray\n }\n break\n case 'AVL':\n indexes[prop] = {\n type: 'AVL',\n node: AVLTree.fromJSON(node),\n isArray\n }\n break\n case 'BKD':\n indexes[prop] = {\n type: 'BKD',\n node: BKDTree.fromJSON(node),\n isArray\n }\n break\n case 'Bool':\n indexes[prop] = {\n type: 'Bool',\n node: BoolNode.fromJSON(node),\n isArray\n }\n break\n default:\n indexes[prop] = rawIndexes[prop]\n }\n }\n\n for (const idx of Object.keys(rawVectorIndexes)) {\n vectorIndexes[idx] = {\n type: 'Vector',\n isArray: false,\n node: VectorIndex.fromJSON(rawVectorIndexes[idx])\n }\n }\n\n return {\n sharedInternalDocumentStore,\n indexes,\n vectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n }\n}\n\nexport function save<R = unknown>(index: Index): R {\n const {\n indexes,\n vectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n } = index\n\n const dumpVectorIndexes: Record<string, unknown> = {}\n for (const idx of Object.keys(vectorIndexes)) {\n dumpVectorIndexes[idx] = vectorIndexes[idx].node.toJSON()\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const savedIndexes: any = {}\n for (const name of Object.keys(indexes)) {\n const { type, node, isArray } = indexes[name]\n if (type === 'Flat'\n || type === 'Radix'\n || type === 'AVL'\n || type === 'BKD'\n || type === 'Bool'\n ) {\n savedIndexes[name] = {\n type,\n node: node.toJSON(),\n isArray\n }\n } else {\n savedIndexes[name] = indexes[name]\n savedIndexes[name].node = savedIndexes[name].node.toJSON()\n }\n }\n\n return {\n indexes: savedIndexes,\n vectorIndexes: dumpVectorIndexes,\n searchableProperties,\n searchablePropertiesWithTypes,\n frequencies,\n tokenOccurrences,\n avgFieldLength,\n fieldLengths\n } as R\n}\n\nexport function createIndex(): IIndex<Index> {\n return {\n create,\n insert,\n remove,\n insertDocumentScoreParameters,\n insertTokenScoreParameters,\n removeDocumentScoreParameters,\n removeTokenScoreParameters,\n calculateResultScores,\n search,\n searchByWhereClause,\n getSearchableProperties,\n getSearchablePropertiesWithTypes,\n load,\n save\n }\n}\n\nfunction addGeoResult(set: Set<InternalDocumentID> | undefined, ids: Array<{ docIDs: InternalDocumentID[] }>): Set<InternalDocumentID> {\n if (!set) {\n set = new Set()\n }\n\n const idsLength = ids.length\n for (let i = 0; i < idsLength; i++) {\n const entry = ids[i].docIDs\n const idsLength = entry.length\n for (let j = 0; j < idsLength; j++) {\n set.add(entry[j])\n }\n }\n\n return set\n}\n\nfunction addFindResult(set: Set<InternalDocumentID> | undefined, filteredIDsResults: FindResult): Set<InternalDocumentID> {\n if (!set) {\n set = new Set()\n }\n\n const keys = Object.keys(filteredIDsResults)\n const keysLength = keys.length\n for (let i = 0; i < keysLength; i++) {\n const ids = filteredIDsResults[keys[i]]\n const idsLength = ids.length\n for (let j = 0; j < idsLength; j++) {\n set.add(ids[j])\n }\n }\n\n return set\n}\n","/* eslint-disable no-extra-semi */\n/* eslint-disable @typescript-eslint/no-this-alias */\nimport { Nullable } from '../types.js'\nimport { setUnion } from '../utils.js'\n\nexport class AVLNode<K, V> {\n public k: K\n public v: Set<V>\n public l: Nullable<AVLNode<K, V>> = null\n public r: Nullable<AVLNode<K, V>> = null\n public h: number = 1\n\n constructor(key: K, value: V[]) {\n this.k = key\n this.v = new Set(value)\n }\n\n public updateHeight(): void {\n this.h = Math.max(AVLNode.getHeight(this.l), AVLNode.getHeight(this.r)) + 1\n }\n\n public static getHeight<K, V>(node: Nullable<AVLNode<K, V>>): number {\n return node ? node.h : 0\n }\n\n public getBalanceFactor(): number {\n return AVLNode.getHeight(this.l) - AVLNode.getHeight(this.r)\n }\n\n public rotateLeft(): AVLNode<K, V> {\n const newRoot = this.r as AVLNode<K, V>\n this.r = newRoot.l\n newRoot.l = this\n this.updateHeight()\n newRoot.updateHeight()\n return newRoot\n }\n\n public rotateRight(): AVLNode<K, V> {\n const newRoot = this.l as AVLNode<K, V>\n this.l = newRoot.r\n newRoot.r = this\n this.updateHeight()\n newRoot.updateHeight()\n return newRoot\n }\n\n public toJSON(): object {\n return {\n k: this.k,\n v: Array.from(this.v),\n l: this.l ? this.l.toJSON() : null,\n r: this.r ? this.r.toJSON() : null,\n h: this.h\n }\n }\n\n public static fromJSON<K, V>(json: any): AVLNode<K, V> {\n const node = new AVLNode<K, V>(json.k, json.v)\n node.l = json.l ? AVLNode.fromJSON<K, V>(json.l) : null\n node.r = json.r ? AVLNode.fromJSON<K, V>(json.r) : null\n node.h = json.h\n return node\n }\n}\n\nexport class AVLTree<K, V> {\n public root: Nullable<AVLNode<K, V>> = null\n private insertCount = 0\n\n constructor(key?: K, value?: V[]) {\n if (key !== undefined && value !== undefined) {\n this.root = new AVLNode(key, value)\n }\n }\n\n public insert(key: K, value: V, rebalanceThreshold = 1000): void {\n this.root = this.insertNode(this.root, key, value, rebalanceThreshold)\n }\n\n public insertMultiple(key: K, value: V[], rebalanceThreshold = 1000): void {\n for (const v of value) {\n this.insert(key, v, rebalanceThreshold)\n }\n }\n\n // Rebalance the tree if the insert count reaches the threshold.\n // This will improve insertion performance since we won't be rebalancing the tree on every insert.\n // When inserting docs using `insertMultiple`, the threshold will be set to the number of docs being inserted.\n // We can force rebalancing the tree by setting the threshold to 1 (default).\n public rebalance() {\n if (this.root) {\n this.root = this.rebalanceNode(this.root!)\n }\n }\n\n public toJSON(): object {\n return {\n root: this.root ? this.root.toJSON() : null,\n insertCount: this.insertCount\n }\n }\n\n public static fromJSON<K, V>(json: any): AVLTree<K, V> {\n const tree = new AVLTree<K, V>()\n tree.root = json.root ? AVLNode.fromJSON<K, V>(json.root) : null\n tree.insertCount = json.insertCount || 0\n return tree\n }\n\n private insertNode(node: Nullable<AVLNode<K, V>>, key: K, value: V, rebalanceThreshold: number): AVLNode<K, V> {\n if (node === null) {\n return new AVLNode(key, [value])\n }\n\n const path: Array<{ parent: Nullable<AVLNode<K, V>>; node: AVLNode<K, V> }> = []\n let current = node\n let parent: Nullable<AVLNode<K, V>> = null\n\n while (current !== null) {\n path.push({ parent, node: current })\n\n if (key < current.k) {\n if (current.l === null) {\n current.l = new AVLNode(key, [value])\n path.push({ parent: current, node: current.l })\n break\n } else {\n parent = current\n current = current.l\n }\n } else if (key > current.k) {\n if (current.r === null) {\n current.r = new AVLNode(key, [value])\n path.push({ parent: current, node: current.r })\n break\n } else {\n parent = current\n current = current.r\n }\n } else {\n // Key already exists\n current.v.add(value)\n /*\n if (Array.isArray(current.v)) {\n if (Array.isArray(value)) {\n ;(current.v as any[]).push(...(value as V[]))\n } else {\n ;(current.v as any[]).push(value)\n }\n } else {\n current.v = new Set([value])\n }\n */\n return node\n }\n }\n\n // Update heights and rebalance if necessary\n let needRebalance = false\n if (this.insertCount++ % rebalanceThreshold === 0) {\n needRebalance = true\n }\n\n for (let i = path.length - 1; i >= 0; i--) {\n const { parent, node: currentNode } = path[i]\n currentNode.updateHeight()\n\n if (needRebalance) {\n const rebalancedNode = this.rebalanceNode(currentNode)\n if (parent) {\n if (parent.l === currentNode) {\n parent.l = rebalancedNode\n } else if (parent.r === currentNode) {\n parent.r = rebalancedNode\n }\n } else {\n // This is the root node\n node = rebalancedNode\n }\n }\n }\n\n return node\n }\n\n private rebalanceNode(node: AVLNode<K, V>): AVLNode<K, V> {\n const balanceFactor = node.getBalanceFactor()\n\n if (balanceFactor > 1) {\n // Left heavy\n if (node.l && node.l.getBalanceFactor() >= 0) {\n // Left Left Case\n return node.rotateRight()\n } else if (node.l) {\n // Left Right Case\n node.l = node.l.rotateLeft()\n return node.rotateRight()\n }\n }\n\n if (balanceFactor < -1) {\n // Right heavy\n if (node.r && node.r.getBalanceFactor() <= 0) {\n // Right Right Case\n return node.rotateLeft()\n } else if (node.r) {\n // Right Left Case\n node.r = node.r.rotateRight()\n return node.rotateLeft()\n }\n }\n\n return node\n }\n\n public find(key: K): Nullable<Set<V>> {\n const node = this.findNodeByKey(key)\n return node ? node.v : null\n }\n\n public contains(key: K): boolean {\n return this.find(key) !== null\n }\n\n public getSize(): number {\n let count = 0\n const stack: Array<Nullable<AVLNode<K, V>>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.l\n }\n current = stack.pop()!\n count++\n current = current.r\n }\n\n return count\n }\n\n public isBalanced(): boolean {\n if (!this.root) return true\n\n const stack: Array<AVLNode<K, V>> = [this.root]\n\n while (stack.length > 0) {\n const node = stack.pop()!\n const balanceFactor = node.getBalanceFactor()\n if (Math.abs(balanceFactor) > 1) {\n return false\n }\n\n if (node.l) stack.push(node.l)\n if (node.r) stack.push(node.r)\n }\n\n return true\n }\n\n public remove(key: K): void {\n this.root = this.removeNode(this.root, key)\n }\n\n public removeDocument(key: K, id: V) {\n const node = this.findNodeByKey(key)\n\n if (!node) {\n return\n }\n\n if (node.v.size === 1) {\n this.root = this.removeNode(this.root, key)\n } else {\n node.v = new Set([...node.v.values()].filter((v) => v !== id))\n }\n }\n\n private findNodeByKey(key: K): Nullable<AVLNode<K, V>> {\n let node = this.root\n while (node) {\n if (key < node.k) {\n node = node.l\n } else if (key > node.k) {\n node = node.r\n } else {\n return node\n }\n }\n return null\n }\n\n private removeNode(node: Nullable<AVLNode<K, V>>, key: K): Nullable<AVLNode<K, V>> {\n if (node === null) return null\n\n const path: Array<AVLNode<K, V>> = []\n let current = node\n\n while (current !== null && current.k !== key) {\n path.push(current)\n if (key < current.k) {\n current = current.l!\n } else {\n current = current.r!\n }\n }\n\n if (current === null) {\n // Key not found\n return node\n }\n\n // Node with only one child or no child\n if (current.l === null || current.r === null) {\n const child = current.l ? current.l : current.r\n\n if (path.length === 0) {\n // Node to be deleted is root\n node = child\n } else {\n const parent = path[path.length - 1]\n if (parent.l === current) {\n parent.l = child\n } else {\n parent.r = child\n }\n }\n } else {\n // Node with two children: Get the inorder successor\n let successorParent = current\n let successor = current.r\n\n while (successor.l !== null) {\n successorParent = successor\n successor = successor.l\n }\n\n // Copy the successor's content to current node\n current.k = successor.k\n current.v = successor.v\n\n // Delete the successor\n if (successorParent.l === successor) {\n successorParent.l = successor.r\n } else {\n successorParent.r = successor.r\n }\n\n current = successorParent\n }\n\n // Update heights and rebalance\n path.push(current)\n for (let i = path.length - 1; i >= 0; i--) {\n const currentNode = path[i]\n currentNode.updateHeight()\n const rebalancedNode = this.rebalanceNode(currentNode)\n if (i > 0) {\n const parent = path[i - 1]\n if (parent.l === currentNode) {\n parent.l = rebalancedNode\n } else if (parent.r === currentNode) {\n parent.r = rebalancedNode\n }\n } else {\n // Root node\n node = rebalancedNode\n }\n }\n\n return node\n }\n\n public rangeSearch(min: K, max: K): Set<V> {\n let result: Set<V> = new Set()\n const stack: Array<AVLNode<K, V>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.l\n }\n current = stack.pop()!\n if (current.k >= min && current.k <= max) {\n result = setUnion(result, current.v)\n }\n if (current.k > max) {\n break\n }\n current = current.r\n }\n\n return result\n }\n\n public greaterThan(key: K, inclusive = false): Set<V> {\n let result: Set<V> = new Set()\n const stack: Array<AVLNode<K, V>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.r // Traverse right subtree first\n }\n current = stack.pop()!\n if ((inclusive && current.k >= key) || (!inclusive && current.k > key)) {\n result = setUnion(result, current.v)\n } else if (current.k <= key) {\n break // Since we're traversing in descending order, we can break early\n }\n current = current.l\n }\n\n return result\n }\n\n public lessThan(key: K, inclusive = false): Set<V> {\n let result: Set<V> = new Set()\n const stack: Array<AVLNode<K, V>> = []\n let current = this.root\n\n while (current || stack.length > 0) {\n while (current) {\n stack.push(current)\n current = current.l\n }\n current = stack.pop()!\n if ((inclusive && current.k <= key) || (!inclusive && current.k < key)) {\n result = setUnion(result, current.v)\n } else if (current.k > key) {\n break // Since we're traversing in ascending order, we can break early\n }\n current = current.r\n }\n\n return result\n }\n}\n","import { InternalDocumentID } from '../components/internal-document-id-store.js'\nimport { EnumArrComparisonOperator, EnumComparisonOperator, Nullable, ScalarSearchableValue } from '../types.js'\n\nexport class FlatTree {\n numberToDocumentId: Map<ScalarSearchableValue, Set<InternalDocumentID>>\n\n constructor() {\n this.numberToDocumentId = new Map()\n }\n\n insert(key: ScalarSearchableValue, value: InternalDocumentID): void {\n if (this.numberToDocumentId.has(key)) {\n this.numberToDocumentId.get(key)!.add(value)\n } else {\n this.numberToDocumentId.set(key, new Set([value]))\n }\n }\n\n find(key: ScalarSearchableValue): Nullable<InternalDocumentID[]> {\n const idSet = this.numberToDocumentId.get(key)\n return idSet ? Array.from(idSet) : null\n }\n\n remove(key: ScalarSearchableValue): void {\n this.numberToDocumentId.delete(key)\n }\n\n removeDocument(id: InternalDocumentID, key: ScalarSearchableValue): void {\n const idSet = this.numberToDocumentId.get(key)\n if (idSet) {\n idSet.delete(id)\n if (idSet.size === 0) {\n this.numberToDocumentId.delete(key)\n }\n }\n }\n\n contains(key: ScalarSearchableValue): boolean {\n return this.numberToDocumentId.has(key)\n }\n\n getSize(): number {\n let size = 0\n for (const idSet of this.numberToDocumentId.values()) {\n size += idSet.size\n }\n return size\n }\n\n filter(operation: EnumComparisonOperator): InternalDocumentID[] {\n const operationKeys = Object.keys(operation)\n\n if (operationKeys.length !== 1) {\n throw new Error('Invalid operation')\n }\n\n const operationType = operationKeys[0] as keyof EnumComparisonOperator\n\n switch (operationType) {\n case 'eq': {\n const value = operation[operationType]!\n const idSet = this.numberToDocumentId.get(value)\n return idSet ? Array.from(idSet) : []\n }\n case 'in': {\n const values = operation[operationType]!\n const resultSet: Set<InternalDocumentID> = new Set()\n for (const value of values) {\n const idSet = this.numberToDocumentId.get(value)\n if (idSet) {\n for (const id of idSet) {\n resultSet.add(id)\n }\n }\n }\n return Array.from(resultSet)\n }\n case 'nin': {\n const excludeValues = new Set<ScalarSearchableValue>(operation[operationType]!)\n const resultSet: Set<InternalDocumentID> = new Set()\n for (const [key, idSet] of this.numberToDocumentId.entries()) {\n if (!excludeValues.has(key)) {\n for (const id of idSet) {\n resultSet.add(id)\n }\n }\n }\n return Array.from(resultSet)\n }\n default:\n throw new Error('Invalid operation')\n }\n }\n\n filterArr(operation: EnumArrComparisonOperator): InternalDocumentID[] {\n const operationKeys = Object.keys(operation)\n\n if (operationKeys.length !== 1) {\n throw new Error('Invalid operation')\n }\n\n const operationType = operationKeys[0] as keyof EnumArrComparisonOperator\n\n switch (operationType) {\n case 'containsAll': {\n const values = operation[operationType]!\n const idSets = values.map((value) => this.numberToDocumentId.get(value) ?? new Set())\n if (idSets.length === 0) return []\n const intersection = idSets.reduce((prev, curr) => {\n return new Set([...prev].filter((id) => curr.has(id)))\n })\n return Array.from(intersection) as InternalDocumentID[]\n }\n default:\n throw new Error('Invalid operation')\n }\n }\n\n static fromJSON(json: any): FlatTree {\n if (!json.numberToDocumentId) {\n throw new Error('Invalid Flat Tree JSON')\n }\n\n const tree = new FlatTree()\n for (const [key, ids] of json.numberToDocumentId) {\n tree.numberToDocumentId.set(key, new Set(ids))\n }\n return tree\n }\n\n toJSON(): any {\n return {\n numberToDocumentId: Array.from(this.numberToDocumentId.entries()).map(([key, idSet]) => [key, Array.from(idSet)])\n }\n }\n}\n","export type BoundedMetric = {\n isBounded: boolean\n distance: number\n}\n\n/**\n * Inspired by:\n * https://github.com/Yomguithereal/talisman/blob/86ae55cbd040ff021d05e282e0e6c71f2dde21f8/src/metrics/levenshtein.js#L218-L340\n */\nfunction _boundedLevenshtein(term: string, word: string, tolerance: number): number {\n // Handle base cases\n if (tolerance < 0) return -1\n if (term === word) return 0\n\n const m = term.length\n const n = word.length\n\n // Special case for empty strings\n if (m === 0) return n <= tolerance ? n : -1\n if (n === 0) return m <= tolerance ? m : -1\n\n // term = term.toLowerCase()\n // word = word.toLowerCase()\n\n const diff = Math.abs(m - n)\n // Special case for prefixes\n // If the searching word starts with the indexed word, return early.\n if (term.startsWith(word)) {\n // We just check if the remaining characters are within the tolerance\n return diff <= tolerance ? diff : -1\n }\n // If the indexed word starts with the searching word, return early.\n if (word.startsWith(term)) {\n // any prefixed word is within the tolerance\n return 0\n }\n\n // If the length difference is greater than the tolerance, return early\n if (diff > tolerance) return -1\n\n // Initialize the matrix\n const matrix: number[][] = []\n for (let i = 0; i <= m; i++) {\n matrix[i] = [i]\n for (let j = 1; j <= n; j++) {\n matrix[i][j] = i === 0 ? j : 0\n }\n }\n\n // Fill the matrix\n for (let i = 1; i <= m; i++) {\n let rowMin = Infinity\n for (let j = 1; j <= n; j++) {\n if (term[i - 1] === word[j - 1]) {\n matrix[i][j] = matrix[i - 1][j - 1]\n } else {\n matrix[i][j] = Math.min(\n matrix[i - 1][j] + 1, // deletion\n matrix[i][j - 1] + 1, // insertion\n matrix[i - 1][j - 1] + 1 // substitution\n )\n }\n rowMin = Math.min(rowMin, matrix[i][j])\n }\n\n // Early termination if all values in this row exceed tolerance\n if (rowMin > tolerance) {\n return -1\n }\n }\n\n return matrix[m][n] <= tolerance ? matrix[m][n] : -1\n}\n\n/**\n * Computes the Levenshtein distance between two strings (a, b), returning early with -1 if the distance\n * is greater than the given tolerance.\n * It assumes that:\n * - tolerance >= ||a| - |b|| >= 0\n */\nexport function boundedLevenshtein(term: string, w: string, tolerance: number): BoundedMetric {\n const distance = _boundedLevenshtein(term, w, tolerance)\n return {\n distance,\n isBounded: distance >= 0\n }\n}\n\n// This is only used internally, keep in sync with the previous one\nexport function syncBoundedLevenshtein(term: string, w: string, tolerance: number): BoundedMetric {\n const distance = _boundedLevenshtein(term, w, tolerance)\n return {\n distance,\n isBounded: distance >= 0\n }\n}\n\nexport function levenshtein(a: string, b: string): number {\n /* c8 ignore next 3 */\n if (!a.length) {\n return b.length\n }\n\n /* c8 ignore next 3 */\n if (!b.length) {\n return a.length\n }\n\n const swap = a\n if (a.length > b.length) {\n a = b\n b = swap\n }\n\n const row = Array.from({ length: a.length + 1 }, (_, i) => i)\n let val = 0\n\n for (let i = 1; i <= b.length; i++) {\n let prev = i\n\n for (let j = 1; j <= a.length; j++) {\n if (b[i - 1] === a[j - 1]) {\n val = row[j - 1]\n } else {\n val = Math.min(row[j - 1] + 1, Math.min(prev + 1, row[j] + 1))\n }\n\n row[j - 1] = prev\n prev = val\n }\n row[a.length] = prev\n }\n\n return row[a.length]\n}\n","/* eslint-disable @typescript-eslint/no-this-alias */\nimport { syncBoundedLevenshtein } from '../components/levenshtein.js'\nimport { InternalDocumentID } from '../components/internal-document-id-store.js'\nimport { getOwnProperty } from '../utils.js'\n\ninterface FindParams {\n term: string\n exact?: boolean\n tolerance?: number\n}\n\nexport type FindResult = Record<string, InternalDocumentID[]>\n\nexport class RadixNode {\n // Node key\n public k: string\n // Node subword\n public s: string\n // Node children\n public c: Map<string, RadixNode> = new Map()\n // Node documents\n public d: Set<InternalDocumentID> = new Set()\n // Node end\n public e: boolean\n // Node word\n public w = ''\n\n constructor(key: string, subWord: string, end: boolean) {\n this.k = key\n this.s = subWord\n this.e = end\n }\n\n public updateParent(parent: RadixNode): void {\n this.w = parent.w + this.s\n }\n\n public addDocument(docID: InternalDocumentID): void {\n this.d.add(docID)\n }\n\n public removeDocument(docID: InternalDocumentID): boolean {\n return this.d.delete(docID)\n }\n\n public findAllWords(output: FindResult, term: string, exact?: boolean, tolerance?: number): FindResult {\n const stack: RadixNode[] = [this]\n while (stack.length > 0) {\n const node = stack.pop()!\n \n if (node.e) {\n const { w, d: docIDs } = node\n \n if (exact && w !== term) {\n continue\n }\n\n // check if _output[w] exists and then add the doc to it\n // always check in own property to prevent access to inherited properties\n // fix https://github.com/oramasearch/orama/issues/137\n if (getOwnProperty(output, w) !== null) {\n if (tolerance) {\n const difference = Math.abs(term.length - w.length)\n \n if (difference <= tolerance && syncBoundedLevenshtein(term, w, tolerance).isBounded) {\n output[w] = []\n } else {\n continue\n }\n } else {\n output[w] = []\n }\n } \n\n // check if _output[w] exists and then add the doc to it\n // always check in own property to prevent access to inherited properties\n // fix https://github.com/oramasearch/orama/issues/137\n if (getOwnProperty(output, w) != null && docIDs.size > 0) {\n const docs = output[w]\n for (const docID of docIDs) {\n if (!docs.includes(docID)) {\n docs.push(docID)\n }\n }\n }\n }\n \n if (node.c.size > 0) {\n stack.push(...node.c.values())\n }\n }\n return output\n } \n\n public insert(word: string, docId: InternalDocumentID): void {\n let node: RadixNode = this\n let i = 0\n const wordLength = word.length\n \n while (i < wordLength) {\n const currentCharacter = word[i]\n const childNode = node.c.get(currentCharacter)\n \n if (childNode) {\n const edgeLabel = childNode.s\n const edgeLabelLength = edgeLabel.length\n let j = 0\n \n // Find the common prefix length between edgeLabel and the remaining word\n while (j < edgeLabelLength && i + j < wordLength && edgeLabel[j] === word[i + j]) {\n j++\n }\n \n if (j === edgeLabelLength) {\n // Edge label fully matches; proceed to the child node\n node = childNode\n i += j\n if (i === wordLength) {\n // The word is a prefix of an existing word\n if (!childNode.e) {\n childNode.e = true\n }\n childNode.addDocument(docId)\n return\n }\n continue\n }\n \n // Split the edgeLabel at the common prefix\n const commonPrefix = edgeLabel.slice(0, j)\n const newEdgeLabel = edgeLabel.slice(j)\n const newWordLabel = word.slice(i + j)\n \n // Create an intermediate node for the common prefix\n const inbetweenNode = new RadixNode(commonPrefix[0], commonPrefix, false)\n node.c.set(commonPrefix[0], inbetweenNode)\n inbetweenNode.updateParent(node)\n \n // Update the existing childNode\n childNode.s = newEdgeLabel\n childNode.k = newEdgeLabel[0]\n inbetweenNode.c.set(newEdgeLabel[0], childNode)\n childNode.updateParent(inbetweenNode)\n \n if (newWordLabel) {\n // Create a new node for the remaining part of the word\n const newNode = new RadixNode(newWordLabel[0], newWordLabel, true)\n newNode.addDocument(docId)\n inbetweenNode.c.set(newWordLabel[0], newNode)\n newNode.updateParent(inbetweenNode)\n } else {\n // The word ends at the inbetweenNode\n inbetweenNode.e = true\n inbetweenNode.addDocument(docId)\n }\n return\n } else {\n // No matching child; create a new node\n const newNode = new RadixNode(currentCharacter, word.slice(i), true)\n newNode.addDocument(docId)\n node.c.set(currentCharacter, newNode)\n newNode.updateParent(node)\n return\n }\n }\n \n // If we reach here, the word already exists in the tree\n if (!node.e) {\n node.e = true\n }\n node.addDocument(docId)\n } \n\n private _findLevenshtein(\n term: string,\n index: number,\n tolerance: number,\n originalTolerance: number,\n output: FindResult\n ) {\n const stack: Array<{ node: RadixNode; index: number; tolerance: number }> = [{ node: this, index, tolerance }]\n\n while (stack.length > 0) {\n const { node, index, tolerance } = stack.pop()!\n\n if (node.w.startsWith(term)) {\n node.findAllWords(output, term, false, 0)\n continue\n }\n\n if (tolerance < 0) {\n continue\n }\n\n if (node.e) {\n const { w, d: docIDs } = node\n if (w) {\n if (syncBoundedLevenshtein(term, w, originalTolerance).isBounded) {\n output[w] = []\n }\n if (getOwnProperty(output, w) !== undefined && docIDs.size > 0) {\n const docs = new Set(output[w])\n\n for (const docID of docIDs) {\n docs.add(docID)\n }\n output[w] = Array.from(docs)\n }\n }\n }\n\n if (index >= term.length) {\n continue\n }\n\n const currentChar = term[index]\n\n // 1. If node has child matching term[index], push { node: childNode, index +1, tolerance }\n if (node.c.has(currentChar)) {\n const childNode = node.c.get(currentChar)!\n stack.push({ node: childNode, index: index + 1, tolerance })\n }\n\n // 2. Push { node, index +1, tolerance -1 } (Delete operation)\n stack.push({ node: node, index: index + 1, tolerance: tolerance - 1 })\n\n // 3. For each child:\n for (const [character, childNode] of node.c) {\n // a) Insert operation\n stack.push({ node: childNode, index: index, tolerance: tolerance - 1 })\n\n // b) Substitute operation\n if (character !== currentChar) {\n stack.push({ node: childNode, index: index + 1, tolerance: tolerance - 1 })\n }\n }\n }\n }\n\n public find(params: FindParams): FindResult {\n const { term, exact, tolerance } = params\n if (tolerance && !exact) {\n const output: FindResult = {}\n this._findLevenshtein(term, 0, tolerance, tolerance, output)\n return output\n } else {\n let node: RadixNode = this\n let i = 0\n const termLength = term.length\n \n while (i < termLength) {\n const character = term[i]\n const childNode = node.c.get(character)\n \n if (childNode) {\n const edgeLabel = childNode.s\n const edgeLabelLength = edgeLabel.length\n let j = 0\n \n // Compare edge label with the term starting from position i\n while (j < edgeLabelLength && i + j < termLength && edgeLabel[j] === term[i + j]) {\n j++\n }\n \n if (j === edgeLabelLength) {\n // Full match of edge label; proceed to the child node\n node = childNode\n i += j\n } else if (i + j === termLength) {\n // The term ends in the middle of the edge label\n if (exact) {\n // Exact match required but term doesn't end at a node\n return {}\n } else {\n // Partial match; collect words starting from this node\n const output: FindResult = {}\n childNode.findAllWords(output, term, exact, tolerance)\n return output\n }\n } else {\n // Mismatch found\n return {}\n }\n } else {\n // No matching child node\n return {}\n }\n }\n \n // Term fully matched; collect words starting from this node\n const output: FindResult = {}\n node.findAllWords(output, term, exact, tolerance)\n return output\n }\n }\n \n public contains(term: string): boolean {\n let node: RadixNode = this\n let i = 0\n const termLength = term.length\n \n while (i < termLength) {\n const character = term[i]\n const childNode = node.c.get(character)\n \n if (childNode) {\n const edgeLabel = childNode.s\n const edgeLabelLength = edgeLabel.length\n let j = 0\n \n while (j < edgeLabelLength && i + j < termLength && edgeLabel[j] === term[i + j]) {\n j++\n }\n \n if (j < edgeLabelLength) {\n return false\n }\n \n i += edgeLabelLength\n node = childNode\n } else {\n return false\n }\n }\n return true\n } \n\n public removeWord(term: string): boolean {\n if (!term) {\n return false\n }\n\n let node: RadixNode = this\n const termLength = term.length\n const stack: { parent: RadixNode; character: string }[] = []\n for (let i = 0; i < termLength; i++) {\n const character = term[i]\n if (node.c.has(character)) {\n const childNode = node.c.get(character)!\n stack.push({ parent: node, character })\n i += childNode.s.length - 1\n node = childNode\n } else {\n return false\n }\n }\n\n // Remove documents from the node\n node.d.clear()\n node.e = false\n\n // Clean up any nodes that no longer lead to a word\n while (stack.length > 0 && node.c.size === 0 && !node.e && node.d.size === 0) {\n const { parent, character } = stack.pop()!\n parent.c.delete(character)\n node = parent\n }\n\n return true\n }\n\n public removeDocumentByWord(term: string, docID: InternalDocumentID, exact = true): boolean {\n if (!term) {\n return true\n }\n\n let node: RadixNode = this\n const termLength = term.length\n for (let i = 0; i < termLength; i++) {\n const character = term[i]\n if (node.c.has(character)) {\n const childNode = node.c.get(character)!\n i += childNode.s.length - 1\n node = childNode\n\n if (exact && node.w !== term) {\n // Do nothing if the exact condition is not met.\n } else {\n node.removeDocument(docID)\n }\n } else {\n return false\n }\n }\n return true\n }\n\n private static getCommonPrefix(a: string, b: string): string {\n const len = Math.min(a.length, b.length)\n let i = 0\n while (i < len && a.charCodeAt(i) === b.charCodeAt(i)) {\n i++\n }\n return a.slice(0, i)\n } \n\n public toJSON(): object {\n return {\n w: this.w,\n s: this.s,\n e: this.e,\n k: this.k,\n d: Array.from(this.d),\n c: Array.from(this.c?.entries())?.map(([key, node]) => [key, node.toJSON()])\n }\n }\n\n public static fromJSON(json: any): RadixNode {\n const node = new RadixNode(json.k, json.s, json.e)\n node.w = json.w\n node.d = new Set(json.d)\n node.c = new Map(json?.c?.map(([key, nodeJson]: [string, any]) => [key, RadixNode.fromJSON(nodeJson)]))\n return node\n }\n}\n\nexport class RadixTree extends RadixNode {\n constructor() {\n super('', '', false)\n }\n\n public static fromJSON(json: any): RadixTree {\n const tree = new RadixTree()\n tree.w = json.w\n tree.s = json.s\n tree.e = json.e\n tree.k = json.k\n tree.d = new Set(json.d)\n tree.c = new Map(json.c?.map(([key, nodeJson]: [string, any]) => [key, RadixNode.fromJSON(nodeJson)]))\n return tree\n }\n\n public toJSON(): object {\n return super.toJSON()\n }\n}","import type { Nullable, GenericSorting } from '../types.js'\nimport type { InternalDocumentID } from '../components/internal-document-id-store.js'\n\nexport interface Point {\n lon: number\n lat: number\n}\n\nexport interface GeoSearchResult {\n point: Point\n docIDs: InternalDocumentID[]\n}\n\nexport type SortGeoPoints = Nullable<GenericSorting>\n\ntype SearchTask = {\n node: Nullable<BKDNode>\n depth: number\n}\n\nconst K = 2 // 2D points\nconst EARTH_RADIUS = 6371e3 // Earth radius in meters\n\nclass BKDNode {\n point: Point\n docIDs: Set<InternalDocumentID>\n left: Nullable<BKDNode>\n right: Nullable<BKDNode>\n parent: Nullable<BKDNode>\n\n constructor(point: Point, docIDs?: InternalDocumentID[]) {\n this.point = point\n this.docIDs = new Set(docIDs)\n this.left = null\n this.right = null\n this.parent = null\n }\n\n toJSON(): any {\n return {\n point: this.point,\n docIDs: Array.from(this.docIDs),\n left: this.left ? this.left.toJSON() : null,\n right: this.right ? this.right.toJSON() : null\n }\n }\n\n static fromJSON(json: any, parent: Nullable<BKDNode> = null): BKDNode {\n const node = new BKDNode(json.point, json.docIDs)\n node.parent = parent\n if (json.left) {\n node.left = BKDNode.fromJSON(json.left, node)\n }\n if (json.right) {\n node.right = BKDNode.fromJSON(json.right, node)\n }\n return node\n }\n}\n\nexport class BKDTree {\n root: Nullable<BKDNode>\n nodeMap: Map<string, BKDNode>\n\n constructor() {\n this.root = null\n this.nodeMap = new Map()\n }\n\n private getPointKey(point: Point): string {\n return `${point.lon},${point.lat}`\n }\n\n insert(point: Point, docIDs: InternalDocumentID[]): void {\n const pointKey = this.getPointKey(point)\n const existingNode = this.nodeMap.get(pointKey)\n if (existingNode) {\n docIDs.forEach((id) => existingNode.docIDs.add(id))\n return\n }\n\n const newNode = new BKDNode(point, docIDs)\n this.nodeMap.set(pointKey, newNode)\n\n if (this.root == null) {\n this.root = newNode\n return\n }\n\n let node = this.root\n let depth = 0\n\n // eslint-disable-next-line no-constant-condition\n while (true) {\n const axis = depth % K\n\n if (axis === 0) {\n if (point.lon < node.point.lon) {\n if (node.left == null) {\n node.left = newNode\n newNode.parent = node\n return\n }\n node = node.left\n } else {\n if (node.right == null) {\n node.right = newNode\n newNode.parent = node\n return\n }\n node = node.right\n }\n } else {\n if (point.lat < node.point.lat) {\n if (node.left == null) {\n node.left = newNode\n newNode.parent = node\n return\n }\n node = node.left\n } else {\n if (node.right == null) {\n node.right = newNode\n newNode.parent = node\n return\n }\n node = node.right\n }\n }\n\n depth++\n }\n }\n\n contains(point: Point): boolean {\n const pointKey = this.getPointKey(point)\n return this.nodeMap.has(pointKey)\n }\n\n getDocIDsByCoordinates(point: Point): Nullable<InternalDocumentID[]> {\n const pointKey = this.getPointKey(point)\n const node = this.nodeMap.get(pointKey)\n if (node) {\n return Array.from(node.docIDs)\n }\n return null\n }\n\n removeDocByID(point: Point, docID: InternalDocumentID): void {\n const pointKey = this.getPointKey(point)\n const node = this.nodeMap.get(pointKey)\n if (node) {\n node.docIDs.delete(docID)\n if (node.docIDs.size === 0) {\n this.nodeMap.delete(pointKey)\n this.deleteNode(node)\n }\n }\n }\n\n private deleteNode(node: BKDNode): void {\n const parent = node.parent\n const child = node.left ? node.left : node.right\n if (child) {\n child.parent = parent\n }\n\n if (parent) {\n if (parent.left === node) {\n parent.left = child\n } else if (parent.right === node) {\n parent.right = child\n }\n } else {\n this.root = child\n if (this.root) {\n this.root.parent = null\n }\n }\n }\n\n searchByRadius(\n center: Point,\n radius: number,\n inclusive = true,\n sort: SortGeoPoints = 'asc',\n highPrecision = false\n ): GeoSearchResult[] {\n const distanceFn = highPrecision ? BKDTree.vincentyDistance : BKDTree.haversineDistance\n const stack: Array<{ node: Nullable<BKDNode>; depth: number }> = [{ node: this.root, depth: 0 }]\n const result: GeoSearchResult[] = []\n\n while (stack.length > 0) {\n const { node, depth } = stack.pop()!\n if (node == null) continue\n\n const dist = distanceFn(center, node.point)\n\n if (inclusive ? dist <= radius : dist > radius) {\n result.push({ point: node.point, docIDs: Array.from(node.docIDs) })\n }\n\n if (node.left != null) {\n stack.push({ node: node.left, depth: depth + 1 })\n }\n if (node.right != null) {\n stack.push({ node: node.right, depth: depth + 1 })\n }\n }\n\n if (sort) {\n result.sort((a, b) => {\n const distA = distanceFn(center, a.point)\n const distB = distanceFn(center, b.point)\n return sort.toLowerCase() === 'asc' ? distA - distB : distB - distA\n })\n }\n\n return result\n }\n\n searchByPolygon(\n polygon: Point[],\n inclusive = true,\n sort: SortGeoPoints = null,\n highPrecision = false\n ): GeoSearchResult[] {\n const stack: SearchTask[] = [{ node: this.root, depth: 0 }]\n const result: GeoSearchResult[] = []\n\n while (stack.length > 0) {\n const { node, depth } = stack.pop()!\n if (node == null) continue\n\n if (node.left != null) {\n stack.push({ node: node.left, depth: depth + 1 })\n }\n if (node.right != null) {\n stack.push({ node: node.right, depth: depth + 1 })\n }\n\n const isInsidePolygon = BKDTree.isPointInPolygon(polygon, node.point)\n\n if ((isInsidePolygon && inclusive) || (!isInsidePolygon && !inclusive)) {\n result.push({ point: node.point, docIDs: Array.from(node.docIDs) })\n }\n }\n\n const centroid = BKDTree.calculatePolygonCentroid(polygon)\n\n if (sort) {\n const distanceFn = highPrecision ? BKDTree.vincentyDistance : BKDTree.haversineDistance\n result.sort((a, b) => {\n const distA = distanceFn(centroid, a.point)\n const distB = distanceFn(centroid, b.point)\n return sort!.toLowerCase() === 'asc' ? distA - distB : distB - distA\n })\n }\n\n return result\n }\n\n toJSON(): any {\n return {\n root: this.root ? this.root.toJSON() : null\n }\n }\n\n static fromJSON(json: any): BKDTree {\n const tree = new BKDTree()\n if (json.root) {\n tree.root = BKDNode.fromJSON(json.root)\n tree.buildNodeMap(tree.root)\n }\n return tree\n }\n\n private buildNodeMap(node: Nullable<BKDNode>): void {\n if (node == null) return\n const pointKey = this.getPointKey(node.point)\n this.nodeMap.set(pointKey, node)\n if (node.left) {\n this.buildNodeMap(node.left)\n }\n if (node.right) {\n this.buildNodeMap(node.right)\n }\n }\n\n static calculatePolygonCentroid(polygon: Point[]): Point {\n let totalArea = 0\n let centroidX = 0\n let centroidY = 0\n\n const polygonLength = polygon.length\n for (let i = 0, j = polygonLength - 1; i < polygonLength; j = i++) {\n const xi = polygon[i].lon\n const yi = polygon[i].lat\n const xj = polygon[j].lon\n const yj = polygon[j].lat\n\n const areaSegment = xi * yj - xj * yi\n totalArea += areaSegment\n\n centroidX += (xi + xj) * areaSegment\n centroidY += (yi + yj) * areaSegment\n }\n\n totalArea /= 2\n const centroidCoordinate = 6 * totalArea\n\n centroidX /= centroidCoordinate\n centroidY /= centroidCoordinate\n\n return { lon: centroidX, lat: centroidY }\n }\n\n static isPointInPolygon(polygon: Point[], point: Point): boolean {\n let isInside = false\n const x = point.lon\n const y = point.lat\n const polygonLength = polygon.length\n for (let i = 0, j = polygonLength - 1; i < polygonLength; j = i++) {\n const xi = polygon[i].lon\n const yi = polygon[i].lat\n const xj = polygon[j].lon\n const yj = polygon[j].lat\n\n const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi\n if (intersect) isInside = !isInside\n }\n\n return isInside\n }\n\n static haversineDistance(coord1: Point, coord2: Point): number {\n const P = Math.PI / 180\n const lat1 = coord1.lat * P\n const lat2 = coord2.lat * P\n const deltaLat = (coord2.lat - coord1.lat) * P\n const deltaLon = (coord2.lon - coord1.lon) * P\n\n const a =\n Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +\n Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLon / 2) * Math.sin(deltaLon / 2)\n const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))\n\n return EARTH_RADIUS * c\n }\n\n static vincentyDistance(coord1: Point, coord2: Point): number {\n const a = 6378137\n const f = 1 / 298.257223563\n const b = (1 - f) * a\n\n const P = Math.PI / 180\n const lat1 = coord1.lat * P\n const lat2 = coord2.lat * P\n const deltaLon = (coord2.lon - coord1.lon) * P\n\n const U1 = Math.atan((1 - f) * Math.tan(lat1))\n const U2 = Math.atan((1 - f) * Math.tan(lat2))\n\n const sinU1 = Math.sin(U1)\n const cosU1 = Math.cos(U1)\n const sinU2 = Math.sin(U2)\n const cosU2 = Math.cos(U2)\n\n let lambda = deltaLon\n let prevLambda\n let iterationLimit = 1000\n let sinSigma\n let cosSigma\n let sigma\n let sinAlpha\n let cos2Alpha\n let cos2SigmaM\n\n do {\n const sinLambda = Math.sin(lambda)\n const cosLambda = Math.cos(lambda)\n\n sinSigma = Math.sqrt(\n cosU2 * sinLambda * (cosU2 * sinLambda) +\n (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda)\n )\n\n if (sinSigma === 0) return 0 // co-incident points\n\n cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda\n sigma = Math.atan2(sinSigma, cosSigma)\n\n sinAlpha = (cosU1 * cosU2 * sinLambda) / sinSigma\n cos2Alpha = 1 - sinAlpha * sinAlpha\n cos2SigmaM = cosSigma - (2 * sinU1 * sinU2) / cos2Alpha\n\n if (isNaN(cos2SigmaM)) cos2SigmaM = 0\n\n const C = (f / 16) * cos2Alpha * (4 + f * (4 - 3 * cos2Alpha))\n prevLambda = lambda\n lambda =\n deltaLon +\n (1 - C) *\n f *\n sinAlpha *\n (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)))\n } while (Math.abs(lambda - prevLambda) > 1e-12 && --iterationLimit > 0)\n\n if (iterationLimit === 0) {\n return NaN\n }\n\n const uSquared = (cos2Alpha * (a * a - b * b)) / (b * b)\n const A = 1 + (uSquared / 16384) * (4096 + uSquared * (-768 + uSquared * (320 - 175 * uSquared)))\n const B = (uSquared / 1024) * (256 + uSquared * (-128 + uSquared * (74 - 47 * uSquared)))\n\n const deltaSigma =\n B *\n sinSigma *\n (cos2SigmaM +\n (B / 4) *\n (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -\n (B / 6) * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)))\n\n const s = b * A * (sigma - deltaSigma)\n\n return s\n }\n}\n","export class BoolNode<V = unknown> {\n true: Set<V>\n false: Set<V>\n\n constructor() {\n this.true = new Set()\n this.false = new Set()\n }\n\n insert(value: V, bool: boolean): void {\n if (bool) {\n this.true.add(value)\n } else {\n this.false.add(value)\n }\n }\n\n delete(value: V, bool: boolean): void {\n if (bool) {\n this.true.delete(value)\n } else {\n this.false.delete(value)\n }\n }\n\n getSize(): number {\n return this.true.size + this.false.size\n }\n\n toJSON(): any {\n return {\n true: Array.from(this.true),\n false: Array.from(this.false)\n }\n }\n\n static fromJSON<V>(json: any): BoolNode<V> {\n const node = new BoolNode<V>()\n node.true = new Set(json.true)\n node.false = new Set(json.false)\n return node\n }\n}\n","import { createError } from '../errors.js'\nimport { TokenScore, BM25Params } from '../types.js'\nimport { InternalDocumentID } from './internal-document-id-store.js'\n\nexport function prioritizeTokenScores(\n arrays: TokenScore[][],\n boost: number,\n threshold = 0,\n keywordsCount: number\n): TokenScore[] {\n if (boost === 0) {\n throw createError('INVALID_BOOST_VALUE')\n }\n\n const tokenScoresMap = new Map<InternalDocumentID, [number, number]>()\n\n const mapsLength = arrays.length\n for (let i = 0; i < mapsLength; i++) {\n const arr = arrays[i]\n\n const entriesLength = arr.length\n for (let j = 0; j < entriesLength; j++) {\n const [token, score] = arr[j]\n const boostScore = score * boost\n const oldScore = tokenScoresMap.get(token)?.[0]\n\n if (oldScore !== undefined) {\n tokenScoresMap.set(token, [oldScore * 1.5 + boostScore, (tokenScoresMap?.get(token)?.[1] || 0) + 1])\n } else {\n tokenScoresMap.set(token, [boostScore, 1])\n }\n }\n }\n\n const tokenScores: TokenScore[] = []\n\n for (const tokenScoreEntry of tokenScoresMap.entries()) {\n tokenScores.push([tokenScoreEntry[0], tokenScoreEntry[1][0]])\n }\n\n const results = tokenScores.sort((a, b) => b[1] - a[1])\n\n // If threshold is 1, it means we will return all the results with at least one search term,\n // prioritizig the ones that contains more search terms (fuzzy match)\n if (threshold === 1) {\n return results\n }\n\n // Prepare keywords count tracking for threshold handling\n const allResults = results.length\n const tokenScoreWithKeywordsCount: [InternalDocumentID, number, number][] = []\n\n for (const tokenScoreEntry of tokenScoresMap.entries()) {\n tokenScoreWithKeywordsCount.push([tokenScoreEntry[0], tokenScoreEntry[1][0], tokenScoreEntry[1][1]])\n }\n\n // Find the index of the last result with all keywords.\n // Order the documents by the number of keywords they contain, and then by the score.\n const keywordsPerToken = tokenScoreWithKeywordsCount.sort((a, b) => {\n // Compare by the third element, higher numbers first\n if (a[2] > b[2]) return -1\n if (a[2] < b[2]) return 1\n\n // If the third elements are equal, compare by the second element, higher numbers first\n if (a[1] > b[1]) return -1\n if (a[1] < b[1]) return 1\n\n // If both the second and third elements are equal, consider the elements equal\n return 0\n })\n\n let lastTokenWithAllKeywords: number | undefined = undefined\n for (let i = 0; i < allResults; i++) {\n if (keywordsPerToken[i][2] === keywordsCount) {\n lastTokenWithAllKeywords = i\n } else {\n break\n }\n }\n\n // If no results had all the keywords, either bail out earlier or normalize\n if (typeof lastTokenWithAllKeywords === 'undefined') {\n if (threshold === 0) {\n return []\n }\n\n lastTokenWithAllKeywords = 0\n }\n\n const keywordsPerTokenLength = keywordsPerToken.length\n const resultsWithIdAndScore: [number, number][] = new Array(keywordsPerTokenLength)\n for (let i = 0; i < keywordsPerTokenLength; i++) {\n resultsWithIdAndScore[i] = [keywordsPerToken[i][0], keywordsPerToken[i][1]]\n }\n\n // If threshold is 0, it means we will only return all the results that contains ALL the search terms (exact match)\n if (threshold === 0) {\n return resultsWithIdAndScore.slice(0, lastTokenWithAllKeywords + 1)\n }\n\n // If the threshold is between 0 and 1, we will return all the results that contains at least the threshold of search terms\n // For example, if threshold is 0.5, we will return all the results that contains at least 50% of the search terms\n // (fuzzy match with a minimum threshold)\n const thresholdLength =\n lastTokenWithAllKeywords + Math.ceil((threshold * 100 * (allResults - lastTokenWithAllKeywords)) / 100)\n\n return resultsWithIdAndScore.slice(0, allResults + thresholdLength)\n}\n\nexport function BM25(\n tf: number,\n matchingCount: number,\n docsCount: number,\n fieldLength: number,\n averageFieldLength: number,\n { k, b, d }: Required<BM25Params>\n) {\n const idf = Math.log(1 + (docsCount - matchingCount + 0.5) / (matchingCount + 0.5))\n return (idf * (d + tf * (k + 1))) / (tf + k * (1 - b + (b * fieldLength) / averageFieldLength))\n}\n","import { InternalDocumentID } from \"../components/internal-document-id-store.js\"\n\nexport type Magnitude = number\nexport type VectorType = Float32Array\nexport type VectorTypeLike = number[] | VectorType\n\nexport type SimilarVector = [number, number]\n\nexport const DEFAULT_SIMILARITY = 0.8\n\nexport class VectorIndex {\n private vectors: Map<InternalDocumentID, [Magnitude, VectorType]> = new Map()\n\n constructor(\n public size: number,\n ) {}\n\n add(internalDocumentId: InternalDocumentID, value: VectorTypeLike) {\n if (!(value instanceof Float32Array)) {\n value = new Float32Array(value)\n }\n\n const magnitude = getMagnitude(value, this.size)\n this.vectors.set(internalDocumentId, [magnitude, value])\n }\n\n remove(internalDocumentId: InternalDocumentID) {\n this.vectors.delete(internalDocumentId)\n }\n\n find(vector: VectorTypeLike, similarity: number, whereFiltersIDs: Set<InternalDocumentID> | undefined): SimilarVector[] {\n if (!(vector instanceof Float32Array)) {\n vector = new Float32Array(vector)\n }\n\n const results = findSimilarVectors(\n vector,\n whereFiltersIDs,\n this.vectors,\n this.size, similarity\n )\n\n return results\n }\n\n public toJSON(): { size: number, vectors: [InternalDocumentID, [Magnitude, number[]]][] } {\n const vectors: [InternalDocumentID, [Magnitude, number[]]][] = []\n\n for (const [id, [magnitude, vector]] of this.vectors) {\n vectors.push([id, [magnitude, Array.from(vector)]])\n }\n\n return {\n size: this.size,\n vectors,\n }\n }\n\n public static fromJSON(json: any): VectorIndex {\n const raw: { size: number, vectors: [InternalDocumentID, [Magnitude, number[]]][] } = json\n \n const index = new VectorIndex(raw.size)\n for (const [id, [magnitude, vector]] of raw.vectors) {\n index.vectors.set(id, [magnitude, new Float32Array(vector)])\n }\n\n return index\n }\n}\n\n\nexport function getMagnitude(vector: Float32Array, vectorLength: number): number {\n let magnitude = 0\n for (let i = 0; i < vectorLength; i++) {\n magnitude += vector[i] * vector[i]\n }\n return Math.sqrt(magnitude)\n}\n\n// @todo: Write plugins for Node and Browsers to use parallel computation for this function\nexport function findSimilarVectors(\n targetVector: Float32Array,\n keys: Set<InternalDocumentID> | undefined,\n vectors: Map<InternalDocumentID, [Magnitude, VectorType]>,\n length: number,\n threshold\n): SimilarVector[] {\n const targetMagnitude = getMagnitude(targetVector, length)\n\n const similarVectors: SimilarVector[] = []\n\n const base = keys ? keys : vectors.keys()\n for (const vectorId of base) {\n const entry = vectors.get(vectorId)\n if (!entry) {\n continue\n }\n const magnitude = entry[0]\n const vector = entry[1]\n\n let dotProduct = 0\n for (let i = 0; i < length; i++) {\n dotProduct += targetVector[i] * vector[i]\n }\n\n const similarity = dotProduct / (targetMagnitude * magnitude)\n\n if (similarity >= threshold) {\n similarVectors.push([vectorId, similarity])\n }\n }\n\n return similarVectors\n}\n","// eslint-disable-next-line @typescript-eslint/ban-ts-comment\n// @ts-nocheck\n\nconst step2List = {\n ational: 'ate',\n tional: 'tion',\n enci: 'ence',\n anci: 'ance',\n izer: 'ize',\n bli: 'ble',\n alli: 'al',\n entli: 'ent',\n eli: 'e',\n ousli: 'ous',\n ization: 'ize',\n ation: 'ate',\n ator: 'ate',\n alism: 'al',\n iveness: 'ive',\n fulness: 'ful',\n ousness: 'ous',\n aliti: 'al',\n iviti: 'ive',\n biliti: 'ble',\n logi: 'log'\n}\n\nconst step3List = {\n icate: 'ic',\n ative: '',\n alize: 'al',\n iciti: 'ic',\n ical: 'ic',\n ful: '',\n ness: ''\n}\n\n// Consonant\nconst c = '[^aeiou]'\n// Vowel\nconst v = '[aeiouy]'\n// Consonant sequence\nconst C = c + '[^aeiouy]*'\n// Vowel sequence\nconst V = v + '[aeiou]*'\n\n// [C]VC... is m>0\nconst mgr0 = '^(' + C + ')?' + V + C\n// [C]VC[V] is m=1\nconst meq1 = '^(' + C + ')?' + V + C + '(' + V + ')?$'\n// [C]VCVC... is m>1\nconst mgr1 = '^(' + C + ')?' + V + C + V + C\n// vowel in stem\nconst s_v = '^(' + C + ')?' + v\n\nexport function stemmer(w) {\n let stem\n let suffix\n let re\n let re2\n let re3\n let re4\n\n if (w.length < 3) {\n return w\n }\n\n const firstch = w.substring(0, 1)\n if (firstch == 'y') {\n w = firstch.toUpperCase() + w.substring(1)\n }\n\n re = /^(.+?)(ss|i)es$/\n re2 = /^(.+?)([^s])s$/\n\n if (re.test(w)) {\n w = w.replace(re, '$1$2')\n } else if (re2.test(w)) {\n w = w.replace(re2, '$1$2')\n }\n\n re = /^(.+?)eed$/\n re2 = /^(.+?)(ed|ing)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n re = new RegExp(mgr0)\n if (re.test(fp[1])) {\n re = /.$/\n w = w.replace(re, '')\n }\n } else if (re2.test(w)) {\n const fp = re2.exec(w)\n stem = fp[1]\n re2 = new RegExp(s_v)\n if (re2.test(stem)) {\n w = stem\n re2 = /(at|bl|iz)$/\n re3 = new RegExp('([^aeiouylsz])\\\\1$')\n re4 = new RegExp('^' + C + v + '[^aeiouwxy]$')\n if (re2.test(w)) {\n w = w + 'e'\n } else if (re3.test(w)) {\n re = /.$/\n w = w.replace(re, '')\n } else if (re4.test(w)) {\n w = w + 'e'\n }\n }\n }\n\n re = /^(.+?)y$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n re = new RegExp(s_v)\n if (stem && re.test(stem)) {\n w = stem + 'i'\n }\n }\n\n re =\n /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n suffix = fp?.[2]\n re = new RegExp(mgr0)\n if (stem && re.test(stem)) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n w = stem + step2List[suffix]\n }\n }\n\n re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n suffix = fp?.[2]\n re = new RegExp(mgr0)\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (stem && re.test(stem)) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n w = stem + step3List[suffix]\n }\n }\n\n re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/\n re2 = /^(.+?)(s|t)(ion)$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n re = new RegExp(mgr1)\n if (stem && re.test(stem)) {\n w = stem\n }\n } else if (re2.test(w)) {\n const fp = re2.exec(w)\n stem = fp?.[1] ?? '' + fp?.[2] ?? ''\n re2 = new RegExp(mgr1)\n if (re2.test(stem)) {\n w = stem\n }\n }\n\n re = /^(.+?)e$/\n if (re.test(w)) {\n const fp = re.exec(w)\n stem = fp?.[1]\n re = new RegExp(mgr1)\n re2 = new RegExp(meq1)\n re3 = new RegExp('^' + C + v + '[^aeiouwxy]$')\n if (stem && (re.test(stem) || (re2.test(stem) && !re3.test(stem)))) {\n w = stem\n }\n }\n\n re = /ll$/\n re2 = new RegExp(mgr1)\n if (re.test(w) && re2.test(w)) {\n re = /.$/\n w = w.replace(re, '')\n }\n\n if (firstch == 'y') {\n w = firstch.toLowerCase() + w.substring(1)\n }\n\n return w\n}\n","import { AnyIndexStore, AnyOrama, SearchableType, Tokenizer } from \"@orama/orama\"\nimport { avl, bkd, flat, bool, vector } from '@orama/orama/trees'\nimport {\n getVectorSize, internalDocumentIDStore, isVectorType } from '@orama/orama/components'\n\ntype InternalDocumentID = internalDocumentIDStore.InternalDocumentID;\n\nexport type TreeType = 'AVL' | 'Radix' | 'Bool' | 'Flat' | 'BKD';\nexport type TTree<T = TreeType, N = unknown> = {\n type: T;\n node: N;\n isArray: boolean;\n};\nexport type Tree =\n // We don't store strings inside a tree\n // | TTree<'Radix', radix.RadixNode>\n | TTree<'Position', PositionsStorage>\n | TTree<'AVL', avl.AVLTree<number, InternalDocumentID[]>>\n | TTree<'Bool', bool.BoolNode>\n | TTree<'Flat', flat.FlatTree>\n | TTree<'BKD', bkd.BKDTree>;\n\nconst MAX_POSITION = 15\nexport type PositionStorage = Record<string, number[]>\n// 15 `PositionStorage`s\nexport type PositionsStorage = [\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n PositionStorage,\n]\n\nexport interface PT15IndexStore extends AnyIndexStore {\n indexes: Record<string, Tree>\n searchableProperties: string[]\n searchablePropertiesWithTypes: Record<string, SearchableType>\n}\n\nfunction create_obj() {\n // object with empty prototype to cheap objects\n return Object.create(null)\n}\n\nexport function recursiveCreate<T extends AnyOrama>(indexDatastore: PT15IndexStore, schema: T['schema'], prefix: string) {\n for (const [prop, type] of Object.entries<SearchableType>(schema)) {\n const path = `${prefix}${prefix ? '.' : ''}${prop}`\n\n if (typeof type === 'object' && !Array.isArray(type)) {\n // Nested\n recursiveCreate(indexDatastore, type, path)\n continue\n }\n\n if (isVectorType(type)) {\n indexDatastore.searchableProperties.push(path)\n indexDatastore.searchablePropertiesWithTypes[path] = type\n indexDatastore.vectorIndexes[path] = {\n type: 'Vector',\n node: new vector.VectorIndex(getVectorSize(type)),\n isArray: false,\n }\n } else {\n const isArray = /\\[/.test(type as string)\n switch (type) {\n case 'boolean':\n case 'boolean[]':\n indexDatastore.indexes[path] = { type: 'Bool', node: new bool.BoolNode(), isArray }\n break\n case 'number':\n case 'number[]':\n indexDatastore.indexes[path] = { type: 'AVL', node: new avl.AVLTree<number, InternalDocumentID[]>(0, []), isArray }\n break\n case 'string':\n case 'string[]':\n indexDatastore.indexes[path] = { type: 'Position', node: [\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n create_obj(),\n ], isArray }\n break\n case 'enum':\n case 'enum[]':\n indexDatastore.indexes[path] = { type: 'Flat', node: new flat.FlatTree(), isArray }\n break\n case 'geopoint':\n indexDatastore.indexes[path] = { type: 'BKD', node: new bkd.BKDTree(), isArray }\n break\n default:\n throw new Error('INVALID_SCHEMA_TYPE: ' + path)\n }\n\n indexDatastore.searchableProperties.push(path)\n indexDatastore.searchablePropertiesWithTypes[path] = type\n }\n }\n}\n\nexport function insertString(\n value: string,\n positionsStorage: PositionsStorage,\n prop: string,\n internalId: InternalDocumentID,\n language: string | undefined,\n tokenizer: Tokenizer,\n) {\n const tokens = tokenizer.tokenize(value, language, prop)\n const tokensLength = tokens.length\n for (let i = 0; i < tokensLength; i++) {\n const token = tokens[i]\n const position = MAX_POSITION - get_position(i, tokensLength) - 1\n\n const positionStorage = positionsStorage[position]\n\n const tokenLength = token.length\n for (let j = tokenLength; j > 0; j--) {\n const tokenPart = token.slice(0, j)\n positionStorage[tokenPart] = positionStorage[tokenPart] || []\n positionStorage[tokenPart].push(internalId)\n }\n }\n}\n\nexport function get_position(n: number, totalLength: number) {\n if (totalLength < MAX_POSITION) {\n return n\n }\n // Scale\n return Math.floor(n * MAX_POSITION / totalLength) \n}\n\nexport function searchString(\n tokenizer: Tokenizer,\n term: string,\n positionsStorage: PositionsStorage,\n boostPerProp: number,\n whereFiltersIDs: Set<InternalDocumentID> | undefined,\n) {\n const tokens = tokenizer.tokenize(term)\n\n const ret: Map<number, number> = new Map()\n for (const token of tokens) {\n for (let i = 0; i < MAX_POSITION; i++) {\n const positionStorage = positionsStorage[i]\n if (positionStorage[token]) {\n const a = positionStorage[token]\n const aLength = a.length\n\n for (let j = 0; j < aLength; j++) {\n if (whereFiltersIDs && !whereFiltersIDs.has(a[j])) {\n continue\n }\n\n const id = a[j]\n if (ret.has(id)) {\n ret.set(id, ret.get(id)! + i * boostPerProp)\n } else {\n ret.set(id, i * boostPerProp)\n }\n }\n }\n }\n }\n\n return ret\n}\n\nexport function removeString(\n value: string,\n positionsStorage: PositionsStorage,\n prop: string,\n internalId: InternalDocumentID,\n tokenizer: Tokenizer,\n language: string | undefined,\n) {\n const tokens = tokenizer.tokenize(value, language, prop)\n const tokensLength = tokens.length\n for (let i = 0; i < tokensLength; i++) {\n const token = tokens[i]\n const position = MAX_POSITION - get_position(i, tokensLength) - 1\n\n const positionStorage = positionsStorage[position]\n\n const tokenLength = token.length\n for (let j = tokenLength; j > 0; j--) {\n const tokenPart = token.slice(0, j)\n const a = positionStorage[tokenPart]\n if (a) {\n const index = a.indexOf(internalId)\n if (index !== -1) {\n a.splice(index, 1)\n }\n }\n }\n }\n\n}"],"mappings":"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","names":["src_exports","__export","pluginPT15","STEMMERS","SUPPORTED_LANGUAGES","STEMMERS","baseId","nano","milli","second","sprintf","template","args","replaceArgs","groups","rawWidth","type","position","replacement","width","value","padding","precision","w","getOwnProperty","object","property","mapDistanceToMeters","convertDistanceToMeters","distance","unit","ratio","createError","withIntersection","setIntersection","sets","set1","set2","result","base","other","value","min","i","withUnion","setUnion","allLanguages","SUPPORTED_LANGUAGES","errors","createError","code","args","error","sprintf","IS_ARRAY_TYPE","INNER_TYPE","isVectorType","type","isArrayType","IS_ARRAY_TYPE","getInnerType","INNER_TYPE","getVectorSize","size","createError","getInternalDocumentId","store","id","internalId","currentId","components_exports","__export","calculateResultScores","create","createIndex","getSearchableProperties","getSearchablePropertiesWithTypes","insert","insertDocumentScoreParameters","insertTokenScoreParameters","insertVector","load","remove","removeDocumentScoreParameters","removeTokenScoreParameters","save","search","searchByWhereClause","avl_exports","__export","AVLNode","AVLTree","AVLNode","_AVLNode","key","value","__publicField","node","newRoot","json","AVLTree","_AVLTree","rebalanceThreshold","v","tree","path","current","parent","needRebalance","i","currentNode","rebalancedNode","balanceFactor","count","stack","id","child","successorParent","successor","min","max","result","setUnion","inclusive","flat_exports","__export","FlatTree","FlatTree","_FlatTree","__publicField","key","value","idSet","id","size","operation","operationKeys","operationType","values","resultSet","excludeValues","idSets","intersection","prev","curr","json","tree","ids","_boundedLevenshtein","term","word","tolerance","m","n","diff","matrix","i","j","rowMin","syncBoundedLevenshtein","term","w","tolerance","distance","_boundedLevenshtein","RadixNode","_RadixNode","key","subWord","end","__publicField","parent","docID","output","term","exact","tolerance","stack","node","w","docIDs","getOwnProperty","syncBoundedLevenshtein","docs","word","docId","i","wordLength","currentCharacter","childNode","edgeLabel","edgeLabelLength","j","commonPrefix","newEdgeLabel","newWordLabel","inbetweenNode","newNode","index","originalTolerance","currentChar","character","params","termLength","a","b","len","json","nodeJson","RadixTree","_RadixTree","tree","bkd_exports","__export","BKDTree","BKDNode","_BKDNode","point","docIDs","__publicField","json","parent","node","BKDTree","_BKDTree","pointKey","existingNode","id","newNode","depth","docID","child","center","radius","inclusive","sort","highPrecision","distanceFn","stack","result","dist","a","b","distA","distB","polygon","isInsidePolygon","centroid","tree","totalArea","centroidX","centroidY","polygonLength","i","j","xi","yi","xj","yj","areaSegment","centroidCoordinate","isInside","x","y","coord1","coord2","P","lat1","lat2","deltaLat","deltaLon","f","U1","U2","sinU1","cosU1","sinU2","cosU2","lambda","prevLambda","iterationLimit","sinSigma","cosSigma","sigma","sinAlpha","cos2Alpha","cos2SigmaM","sinLambda","cosLambda","C","uSquared","A","B","deltaSigma","bool_exports","__export","BoolNode","BoolNode","_BoolNode","__publicField","value","bool","json","node","BM25","tf","matchingCount","docsCount","fieldLength","averageFieldLength","k","b","d","vector_exports","__export","DEFAULT_SIMILARITY","VectorIndex","findSimilarVectors","getMagnitude","DEFAULT_SIMILARITY","VectorIndex","_VectorIndex","size","__publicField","internalDocumentId","value","magnitude","getMagnitude","vector","similarity","whereFiltersIDs","findSimilarVectors","vectors","id","json","raw","index","vectorLength","i","targetVector","keys","length","threshold","targetMagnitude","similarVectors","base","vectorId","entry","dotProduct","insertDocumentScoreParameters","index","prop","id","tokens","docsCount","internalId","getInternalDocumentId","insertTokenScoreParameters","token","tokenFrequency","t","tf","removeDocumentScoreParameters","removeTokenScoreParameters","create","orama","sharedInternalDocumentStore","schema","prefix","type","path","isVectorType","VectorIndex","getVectorSize","isArray","BoolNode","AVLTree","RadixTree","FlatTree","BKDTree","createError","insertScalarBuilder","implementation","language","tokenizer","options","value","node","avlRebalanceThreshold","insert","schemaType","insertVector","insertScalar","isArrayType","elements","elementsLength","i","internalDocumentId","removeScalar","remove","innerSchemaType","getInnerType","calculateResultScores","term","ids","bm25Relevance","resultsMap","boostPerProperty","whereFiltersIDs","documentIDs","avgFieldLength","fieldLengths","oramaOccurrences","oramaFrequencies","termOccurrences","documentIDsLength","k","bm25","BM25","searchInProperty","tree","exact","tolerance","tokenLength","searchResult","termsFound","termsFoundLength","j","word","search","propertiesToSearch","boost","relevance","searchByWhereClause","filters","filterKeys","filtersMap","acc","key","param","operation","idx","filteredIDs","setUnion","reqOperation","coordinates","unit","inside","highPrecision","distanceInMeters","convertDistanceToMeters","addGeoResult","raw","filteredIDsResults","addFindResult","operationKeys","results","operationOpt","operationValue","min","max","setIntersection","getSearchableProperties","getSearchablePropertiesWithTypes","load","rawIndexes","rawVectorIndexes","searchableProperties","searchablePropertiesWithTypes","frequencies","tokenOccurrences","indexes","vectorIndexes","save","dumpVectorIndexes","savedIndexes","name","createIndex","set","idsLength","entry","keys","keysLength","c","v","C","mgr0","meq1","mgr1","s_v","MAX_POSITION","create_obj","recursiveCreate","indexDatastore","schema","prefix","prop","type","path","isVectorType","vector_exports","getVectorSize","isArray","bool_exports","avl_exports","flat_exports","bkd_exports","insertString","value","positionsStorage","internalId","language","tokenizer","tokens","tokensLength","i","token","position","get_position","positionStorage","tokenLength","j","tokenPart","n","totalLength","searchString","term","boostPerProp","whereFiltersIDs","ret","a","aLength","id","removeString","index","pluginPT15","schema","createComponents","indexDatastore","recursiveCreate","implementation","indexDatastorage","prop","id","internalId","value","schemaType","language","tokenizer","docsCount","components_exports","storage","item","insertString","removeString","index","term","propertiesToSearch","exact","tolerance","boost","relevance","whereFiltersIDs","maps","propertyLength","max","i","property","boostPerProp","map","searchString","base","score","filters","propName","sharedInternalDocumentStore","raw","dump1","dump2","baseIndex","nonStringIndexes","type","stringIndexes"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orama/plugin-pt15",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "Performant search algorithm optimized for descriptive texts",
5
5
  "keywords": [
6
6
  "orama",
@@ -20,12 +20,12 @@
20
20
  }
21
21
  },
22
22
  "bugs": {
23
- "url": "https://github.com/askorama/orama/issues"
23
+ "url": "https://github.com/oramasearch/orama/issues"
24
24
  },
25
- "homepage": "https://github.com/askorama/orama#readme",
25
+ "homepage": "https://github.com/oramasearch/orama#readme",
26
26
  "repository": {
27
27
  "type": "git",
28
- "url": "git+https://github.com/askorama/orama.git"
28
+ "url": "git+https://github.com/oramasearch/orama.git"
29
29
  },
30
30
  "sideEffects": false,
31
31
  "types": "./dist/index.d.ts",
@@ -43,7 +43,7 @@
43
43
  "typescript": "^5.0.0"
44
44
  },
45
45
  "dependencies": {
46
- "@orama/orama": "3.0.0"
46
+ "@orama/orama": "3.0.2"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsup --config tsup.lib.js",