cry-search 1.0.0 → 1.0.3
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.
- package/CLAUDE.md +144 -13
- package/README.md +111 -5
- package/dist/common/SearchUniverse.d.ts.map +1 -1
- package/dist/common/findInLinkedArrays.d.ts +1 -1
- package/dist/common/findInLinkedArrays.d.ts.map +1 -1
- package/dist/common/numeric/AugmentedMetadata.d.ts +111 -0
- package/dist/common/numeric/AugmentedMetadata.d.ts.map +1 -0
- package/dist/common/numeric/findInLinkedArrays.d.ts +1 -1
- package/dist/common/numeric/index.d.ts +3 -0
- package/dist/common/numeric/index.d.ts.map +1 -1
- package/dist/common/numeric/searchInData.d.ts.map +1 -1
- package/dist/common/numeric/syncSearchArrayMetadata.d.ts +64 -0
- package/dist/common/numeric/syncSearchArrayMetadata.d.ts.map +1 -0
- package/dist/common/numeric/updateSearchLinkedMetadata.d.ts +130 -0
- package/dist/common/numeric/updateSearchLinkedMetadata.d.ts.map +1 -0
- package/dist/common/syncSearchArrayMetadata.d.ts +12 -8
- package/dist/common/syncSearchArrayMetadata.d.ts.map +1 -1
- package/dist/common/updateSearchLinkedMetadata.d.ts +26 -16
- package/dist/common/updateSearchLinkedMetadata.d.ts.map +1 -1
- package/dist/index.cjs +265 -490
- package/dist/index.d.cts +3 -9
- package/dist/index.d.ts +3 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +265 -490
- package/dist/string.cjs +922 -0
- package/dist/string.d.cts +26 -0
- package/dist/string.d.ts +26 -0
- package/dist/string.d.ts.map +1 -0
- package/dist/string.js +890 -0
- package/dist/types/index.d.ts +21 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/matchTokenNumeric.d.ts +17 -2
- package/dist/utils/matchTokenNumeric.d.ts.map +1 -1
- package/dist/utils/sanitiseString.d.ts +7 -3
- package/dist/utils/sanitiseString.d.ts.map +1 -1
- package/dist/utils/tokenize.d.ts.map +1 -1
- package/package.json +14 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// src/types/index.ts
|
|
2
2
|
var DEFAULT_SEARCH_OPTS = {
|
|
3
3
|
matchWords: "start",
|
|
4
|
-
matchNumbers: "startEnd"
|
|
4
|
+
matchNumbers: "startEnd",
|
|
5
|
+
matchNumbersShort: "whole",
|
|
6
|
+
matchNumbersThreshold: 6
|
|
5
7
|
};
|
|
6
8
|
function arrayToSearchableData(items) {
|
|
7
9
|
const map = new Map;
|
|
@@ -129,7 +131,7 @@ function preprocessString(input) {
|
|
|
129
131
|
|
|
130
132
|
// src/utils/sanitiseString.ts
|
|
131
133
|
var RE_DIACRITICS = /[\u0300-\u036f]/g;
|
|
132
|
-
var RE_INVALID_CHARS = /[^a-z0-9
|
|
134
|
+
var RE_INVALID_CHARS = /[^a-z0-9.\-~<>+*!=? ]/g;
|
|
133
135
|
function sanitiseString(input) {
|
|
134
136
|
let result = input;
|
|
135
137
|
result = result.toLowerCase();
|
|
@@ -173,11 +175,16 @@ function tokenize(input, config) {
|
|
|
173
175
|
let tokens = input.split(" ").map((token) => token.trim()).filter((token) => token.length > 0);
|
|
174
176
|
if (config?.replaceTokens) {
|
|
175
177
|
tokens = tokens.map((token) => {
|
|
176
|
-
if (token.startsWith("--")
|
|
178
|
+
if (token.length > 2 && token.startsWith("--")) {
|
|
177
179
|
const withoutPrefix = token.slice(2);
|
|
178
180
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
179
181
|
return replaced ? "--" + replaced : token;
|
|
180
182
|
}
|
|
183
|
+
if (token.length > 1 && token[0] === "-" && /^[a-z]/i.test(token[1])) {
|
|
184
|
+
const withoutPrefix = token.slice(1);
|
|
185
|
+
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
186
|
+
return replaced ? "-" + replaced : token;
|
|
187
|
+
}
|
|
181
188
|
return config.replaceTokens.get(token) ?? token;
|
|
182
189
|
});
|
|
183
190
|
}
|
|
@@ -258,13 +265,6 @@ function prepareStringForSearchNumeric(input, tokensMap) {
|
|
|
258
265
|
}
|
|
259
266
|
|
|
260
267
|
// src/common/string/createSearchArrayMetadata.ts
|
|
261
|
-
var MATCH_MODE_PREFIXES = {
|
|
262
|
-
start: "<",
|
|
263
|
-
end: ">",
|
|
264
|
-
startEnd: "+",
|
|
265
|
-
anywhere: "*",
|
|
266
|
-
whole: "!"
|
|
267
|
-
};
|
|
268
268
|
var PREFIX_TO_MATCH_MODE = {
|
|
269
269
|
"<": "start",
|
|
270
270
|
">": "end",
|
|
@@ -275,155 +275,9 @@ var PREFIX_TO_MATCH_MODE = {
|
|
|
275
275
|
"?": "anywhere"
|
|
276
276
|
};
|
|
277
277
|
var DEFAULT_EXCLUDED_FIELDS = new Set(["_id", "_deleted", "_blocked"]);
|
|
278
|
-
function getValueByPath(obj, path) {
|
|
279
|
-
const parts = path.split(".");
|
|
280
|
-
let current = obj;
|
|
281
|
-
for (let i = 0;i < parts.length; i++) {
|
|
282
|
-
if (current == null)
|
|
283
|
-
return;
|
|
284
|
-
const part = parts[i];
|
|
285
|
-
if (Array.isArray(current)) {
|
|
286
|
-
const remainingPath = parts.slice(i).join(".");
|
|
287
|
-
const results = [];
|
|
288
|
-
for (const item of current) {
|
|
289
|
-
const value = getValueByPath(item, remainingPath);
|
|
290
|
-
if (value !== undefined) {
|
|
291
|
-
if (Array.isArray(value)) {
|
|
292
|
-
results.push(...value);
|
|
293
|
-
} else {
|
|
294
|
-
results.push(value);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
return results.length > 0 ? results : undefined;
|
|
299
|
-
}
|
|
300
|
-
if (typeof current === "object") {
|
|
301
|
-
current = current[part];
|
|
302
|
-
} else {
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
return current;
|
|
307
|
-
}
|
|
308
|
-
function isDotNotation(field) {
|
|
309
|
-
return field.includes(".");
|
|
310
|
-
}
|
|
311
|
-
function getRootField(field) {
|
|
312
|
-
const dotIndex = field.indexOf(".");
|
|
313
|
-
return dotIndex === -1 ? field : field.slice(0, dotIndex);
|
|
314
|
-
}
|
|
315
|
-
function extractStringsFromValue(value, results) {
|
|
316
|
-
if (value == null)
|
|
317
|
-
return;
|
|
318
|
-
if (typeof value === "string") {
|
|
319
|
-
results.push(value);
|
|
320
|
-
} else if (typeof value === "number") {
|
|
321
|
-
results.push(String(value));
|
|
322
|
-
} else if (value instanceof Date) {
|
|
323
|
-
results.push(value.toISOString());
|
|
324
|
-
} else if (Array.isArray(value)) {
|
|
325
|
-
for (const item of value) {
|
|
326
|
-
extractStringsFromValue(item, results);
|
|
327
|
-
}
|
|
328
|
-
} else if (typeof value === "object") {
|
|
329
|
-
for (const v of Object.values(value)) {
|
|
330
|
-
extractStringsFromValue(v, results);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
278
|
function isDeletedOrBlocked(obj) {
|
|
335
279
|
return obj._deleted != null || obj._blocked != null;
|
|
336
280
|
}
|
|
337
|
-
function extractSearchableStringDefault(obj, spec) {
|
|
338
|
-
if (isDeletedOrBlocked(obj)) {
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
if (spec?.enrichSearchObjectFn) {
|
|
342
|
-
spec.enrichSearchObjectFn(obj, spec.searchContext);
|
|
343
|
-
}
|
|
344
|
-
const parts = [];
|
|
345
|
-
const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
|
|
346
|
-
const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
|
|
347
|
-
for (const key of fieldsToSearch) {
|
|
348
|
-
const keyStr = key;
|
|
349
|
-
if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
|
|
350
|
-
continue;
|
|
351
|
-
if (fieldsToExclude.has(key))
|
|
352
|
-
continue;
|
|
353
|
-
const value = isDotNotation(keyStr) ? getValueByPath(obj, keyStr) : obj[key];
|
|
354
|
-
extractStringsFromValue(value, parts);
|
|
355
|
-
}
|
|
356
|
-
return parts.join(" ");
|
|
357
|
-
}
|
|
358
|
-
function prepareObjectForSearch(obj, spec) {
|
|
359
|
-
if (isDeletedOrBlocked(obj)) {
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
if (spec?.extractSearchableStringFn) {
|
|
363
|
-
const searchableString = spec.extractSearchableStringFn(obj);
|
|
364
|
-
if (searchableString === undefined) {
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
return prepareStringForSearch(searchableString);
|
|
368
|
-
}
|
|
369
|
-
return prepareObjectFieldsForSearch(obj, spec);
|
|
370
|
-
}
|
|
371
|
-
function prepareObjectFieldsForSearch(obj, spec) {
|
|
372
|
-
if (spec?.enrichSearchObjectFn) {
|
|
373
|
-
spec.enrichSearchObjectFn(obj, spec.searchContext);
|
|
374
|
-
}
|
|
375
|
-
const allTokens = [];
|
|
376
|
-
const fieldMatchModes = spec?.fieldMatchModes;
|
|
377
|
-
const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
|
|
378
|
-
const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
|
|
379
|
-
const processedRootFields = new Set;
|
|
380
|
-
for (const key of fieldsToSearch) {
|
|
381
|
-
const keyStr = key;
|
|
382
|
-
if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
|
|
383
|
-
continue;
|
|
384
|
-
if (fieldsToExclude.has(key))
|
|
385
|
-
continue;
|
|
386
|
-
const isDot = isDotNotation(keyStr);
|
|
387
|
-
const rootField = getRootField(keyStr);
|
|
388
|
-
let value;
|
|
389
|
-
if (isDot) {
|
|
390
|
-
value = getValueByPath(obj, keyStr);
|
|
391
|
-
} else {
|
|
392
|
-
value = obj[key];
|
|
393
|
-
processedRootFields.add(rootField);
|
|
394
|
-
}
|
|
395
|
-
if (value == null)
|
|
396
|
-
continue;
|
|
397
|
-
const matchMode = fieldMatchModes?.[key];
|
|
398
|
-
const prefix = matchMode ? MATCH_MODE_PREFIXES[matchMode] : "";
|
|
399
|
-
const fieldStrings = [];
|
|
400
|
-
extractStringsFromValue(value, fieldStrings);
|
|
401
|
-
if (fieldStrings.length > 0) {
|
|
402
|
-
const fieldText = fieldStrings.join(" ");
|
|
403
|
-
const tokens2 = prepareStringForSearch(fieldText);
|
|
404
|
-
for (const token of tokens2) {
|
|
405
|
-
allTokens.push(prefix + token);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
return [...new Set(allTokens)].sort();
|
|
410
|
-
}
|
|
411
|
-
function createSearchArrayMetadata(data, spec) {
|
|
412
|
-
const metadata = new Map;
|
|
413
|
-
for (const [id, item] of data) {
|
|
414
|
-
const tokens2 = prepareObjectForSearch(item, spec);
|
|
415
|
-
if (tokens2 !== undefined) {
|
|
416
|
-
metadata.set(id, tokens2);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
return metadata;
|
|
420
|
-
}
|
|
421
|
-
function wrapMetadataLegacy(metadata) {
|
|
422
|
-
return { items: metadata };
|
|
423
|
-
}
|
|
424
|
-
function unwrapMetadataLegacy(legacy) {
|
|
425
|
-
return legacy.items;
|
|
426
|
-
}
|
|
427
281
|
|
|
428
282
|
// src/common/numeric/createSearchArrayMetadata.ts
|
|
429
283
|
var MATCH_MODE_BITS = {
|
|
@@ -457,7 +311,7 @@ function decodeMatchMode(encoded) {
|
|
|
457
311
|
}
|
|
458
312
|
}
|
|
459
313
|
var DEFAULT_EXCLUDED_FIELDS2 = new Set(["_id", "_deleted", "_blocked"]);
|
|
460
|
-
function
|
|
314
|
+
function getValueByPath(obj, path) {
|
|
461
315
|
const parts = path.split(".");
|
|
462
316
|
let current = obj;
|
|
463
317
|
for (let i = 0;i < parts.length; i++) {
|
|
@@ -468,7 +322,7 @@ function getValueByPath2(obj, path) {
|
|
|
468
322
|
const remainingPath = parts.slice(i).join(".");
|
|
469
323
|
const results = [];
|
|
470
324
|
for (const item of current) {
|
|
471
|
-
const value =
|
|
325
|
+
const value = getValueByPath(item, remainingPath);
|
|
472
326
|
if (value !== undefined) {
|
|
473
327
|
if (Array.isArray(value)) {
|
|
474
328
|
results.push(...value);
|
|
@@ -487,10 +341,10 @@ function getValueByPath2(obj, path) {
|
|
|
487
341
|
}
|
|
488
342
|
return current;
|
|
489
343
|
}
|
|
490
|
-
function
|
|
344
|
+
function isDotNotation(field) {
|
|
491
345
|
return field.includes(".");
|
|
492
346
|
}
|
|
493
|
-
function
|
|
347
|
+
function extractStringsFromValue(value, results) {
|
|
494
348
|
if (value == null)
|
|
495
349
|
return;
|
|
496
350
|
if (typeof value === "string") {
|
|
@@ -501,11 +355,11 @@ function extractStringsFromValue2(value, results) {
|
|
|
501
355
|
results.push(value.toISOString());
|
|
502
356
|
} else if (Array.isArray(value)) {
|
|
503
357
|
for (const item of value) {
|
|
504
|
-
|
|
358
|
+
extractStringsFromValue(item, results);
|
|
505
359
|
}
|
|
506
360
|
} else if (typeof value === "object") {
|
|
507
361
|
for (const v of Object.values(value)) {
|
|
508
|
-
|
|
362
|
+
extractStringsFromValue(v, results);
|
|
509
363
|
}
|
|
510
364
|
}
|
|
511
365
|
}
|
|
@@ -536,13 +390,13 @@ function prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap) {
|
|
|
536
390
|
continue;
|
|
537
391
|
if (fieldsToExclude.has(key))
|
|
538
392
|
continue;
|
|
539
|
-
const isDot =
|
|
540
|
-
const value = isDot ?
|
|
393
|
+
const isDot = isDotNotation(keyStr);
|
|
394
|
+
const value = isDot ? getValueByPath(obj, keyStr) : obj[key];
|
|
541
395
|
if (value == null)
|
|
542
396
|
continue;
|
|
543
397
|
const matchMode = fieldMatchModes?.[key];
|
|
544
398
|
const fieldStrings = [];
|
|
545
|
-
|
|
399
|
+
extractStringsFromValue(value, fieldStrings);
|
|
546
400
|
if (fieldStrings.length > 0) {
|
|
547
401
|
const fieldText = fieldStrings.join(" ");
|
|
548
402
|
const datesNormalized = normalizeDates(fieldText);
|
|
@@ -646,14 +500,38 @@ function removeFromSearchMetadataBatchNumeric(metadata, objectIds) {
|
|
|
646
500
|
}
|
|
647
501
|
// src/utils/matchTokenNumeric.ts
|
|
648
502
|
var RE_NUMERIC = /^[\d.\-]+$/;
|
|
503
|
+
function countDigits(str) {
|
|
504
|
+
let count = 0;
|
|
505
|
+
for (let i = 0;i < str.length; i++) {
|
|
506
|
+
const c = str[i];
|
|
507
|
+
if (c !== "." && c !== "-")
|
|
508
|
+
count++;
|
|
509
|
+
}
|
|
510
|
+
return count;
|
|
511
|
+
}
|
|
512
|
+
function getNumericMatchMode(str, opts) {
|
|
513
|
+
const threshold = opts?.matchNumbersThreshold ?? DEFAULT_SEARCH_OPTS.matchNumbersThreshold;
|
|
514
|
+
const digitCount = countDigits(str);
|
|
515
|
+
if (digitCount <= threshold) {
|
|
516
|
+
return opts?.matchNumbersShort ?? DEFAULT_SEARCH_OPTS.matchNumbersShort;
|
|
517
|
+
}
|
|
518
|
+
return opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers;
|
|
519
|
+
}
|
|
649
520
|
function prepareQueryTokens(queryTokenStrs) {
|
|
650
|
-
return queryTokenStrs.
|
|
521
|
+
return queryTokenStrs.filter((str) => {
|
|
522
|
+
if (str === "-" || str === "--" || str === "~")
|
|
523
|
+
return false;
|
|
524
|
+
return true;
|
|
525
|
+
}).map((str) => {
|
|
651
526
|
let overrideMode;
|
|
652
527
|
let negated = false;
|
|
653
528
|
let cleanStr = str;
|
|
654
529
|
if (str.length > 2 && str.startsWith("--")) {
|
|
655
530
|
negated = true;
|
|
656
531
|
cleanStr = str.slice(2);
|
|
532
|
+
} else if (str.length > 1 && str[0] === "-" && /^[a-z]/i.test(str[1])) {
|
|
533
|
+
negated = true;
|
|
534
|
+
cleanStr = str.slice(1);
|
|
657
535
|
} else if (str.length > 1 && str.startsWith("~")) {
|
|
658
536
|
negated = true;
|
|
659
537
|
cleanStr = str.slice(1);
|
|
@@ -676,13 +554,16 @@ function prepareQueryTokens(queryTokenStrs) {
|
|
|
676
554
|
cleanStr = str.slice(1);
|
|
677
555
|
}
|
|
678
556
|
}
|
|
679
|
-
|
|
557
|
+
const result = {
|
|
680
558
|
str: cleanStr,
|
|
681
559
|
id: findTokenId(cleanStr),
|
|
682
|
-
isNumeric: RE_NUMERIC.test(cleanStr)
|
|
683
|
-
overrideMode,
|
|
684
|
-
negated: negated || undefined
|
|
560
|
+
isNumeric: RE_NUMERIC.test(cleanStr)
|
|
685
561
|
};
|
|
562
|
+
if (overrideMode)
|
|
563
|
+
result.overrideMode = overrideMode;
|
|
564
|
+
if (negated)
|
|
565
|
+
result.negated = true;
|
|
566
|
+
return result;
|
|
686
567
|
});
|
|
687
568
|
}
|
|
688
569
|
function matchWithModeNumeric(searchTokenId, searchTokenStr, targetTokenEncoded, opts, overrideMode) {
|
|
@@ -697,8 +578,8 @@ function matchWithModeNumeric(searchTokenId, searchTokenStr, targetTokenEncoded,
|
|
|
697
578
|
} else if (hasExplicitMode) {
|
|
698
579
|
mode = decodeMatchMode(targetTokenEncoded);
|
|
699
580
|
} else {
|
|
700
|
-
const
|
|
701
|
-
mode =
|
|
581
|
+
const isTargetNumeric = RE_NUMERIC.test(targetTokenStr);
|
|
582
|
+
mode = isTargetNumeric ? getNumericMatchMode(targetTokenStr, opts) : opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
|
|
702
583
|
}
|
|
703
584
|
switch (mode) {
|
|
704
585
|
case "start":
|
|
@@ -733,9 +614,8 @@ function binarySearchUint32(arr, target) {
|
|
|
733
614
|
return false;
|
|
734
615
|
}
|
|
735
616
|
function matchPreparedTokenInSortedList(preparedToken, targetTokens, opts) {
|
|
736
|
-
const { str: searchTokenStr, id: searchTokenId,
|
|
737
|
-
|
|
738
|
-
if (effectiveMode === "whole" && searchTokenId !== -1) {
|
|
617
|
+
const { str: searchTokenStr, id: searchTokenId, overrideMode, negated } = preparedToken;
|
|
618
|
+
if (overrideMode === "whole" && searchTokenId !== -1) {
|
|
739
619
|
let hasEncodedTokens = false;
|
|
740
620
|
for (let i = 0;i < targetTokens.length; i++) {
|
|
741
621
|
if (targetTokens[i] > TOKEN_ID_MASK) {
|
|
@@ -752,47 +632,36 @@ function matchPreparedTokenInSortedList(preparedToken, targetTokens, opts) {
|
|
|
752
632
|
if (matchWithModeNumeric(searchTokenId, searchTokenStr, targetEncoded, opts, overrideMode)) {
|
|
753
633
|
return true;
|
|
754
634
|
}
|
|
635
|
+
if (negated) {
|
|
636
|
+
const targetTokenId = decodeTokenId(targetEncoded);
|
|
637
|
+
const targetTokenStr = tokens[targetTokenId];
|
|
638
|
+
if (targetTokenStr) {
|
|
639
|
+
const hasExplicitMode = targetEncoded !== targetTokenId;
|
|
640
|
+
let targetMode;
|
|
641
|
+
if (overrideMode) {
|
|
642
|
+
targetMode = overrideMode;
|
|
643
|
+
} else if (hasExplicitMode) {
|
|
644
|
+
targetMode = decodeMatchMode(targetEncoded);
|
|
645
|
+
} else {
|
|
646
|
+
const isTargetNumeric = RE_NUMERIC.test(targetTokenStr);
|
|
647
|
+
targetMode = isTargetNumeric ? getNumericMatchMode(targetTokenStr, opts) : opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
|
|
648
|
+
}
|
|
649
|
+
if ((targetMode === "start" || targetMode === "startEnd") && searchTokenStr.startsWith(targetTokenStr)) {
|
|
650
|
+
return true;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
755
654
|
}
|
|
756
655
|
return false;
|
|
757
656
|
}
|
|
758
657
|
function matchTokenInSortedListNumeric(searchTokenStr, targetTokens, opts) {
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
cleanStr = searchTokenStr.slice(2);
|
|
765
|
-
} else if (searchTokenStr.length > 1 && searchTokenStr.startsWith("~")) {
|
|
766
|
-
negated = true;
|
|
767
|
-
cleanStr = searchTokenStr.slice(1);
|
|
768
|
-
} else if (searchTokenStr.length > 3 && searchTokenStr.startsWith("...")) {
|
|
769
|
-
overrideMode = "end";
|
|
770
|
-
cleanStr = searchTokenStr.slice(3);
|
|
771
|
-
} else if (searchTokenStr.length > 2 && searchTokenStr.startsWith("..")) {
|
|
772
|
-
overrideMode = "end";
|
|
773
|
-
cleanStr = searchTokenStr.slice(2);
|
|
774
|
-
} else if (searchTokenStr.length > 3 && searchTokenStr.endsWith("...")) {
|
|
775
|
-
overrideMode = "start";
|
|
776
|
-
cleanStr = searchTokenStr.slice(0, -3);
|
|
777
|
-
} else if (searchTokenStr.length > 2 && searchTokenStr.endsWith("..")) {
|
|
778
|
-
overrideMode = "start";
|
|
779
|
-
cleanStr = searchTokenStr.slice(0, -2);
|
|
780
|
-
} else if (searchTokenStr.length > 1) {
|
|
781
|
-
const firstChar = searchTokenStr[0];
|
|
782
|
-
if (firstChar && PREFIX_TO_MATCH_MODE[firstChar]) {
|
|
783
|
-
overrideMode = PREFIX_TO_MATCH_MODE[firstChar];
|
|
784
|
-
cleanStr = searchTokenStr.slice(1);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
const preparedToken = {
|
|
788
|
-
str: cleanStr,
|
|
789
|
-
id: findTokenId(cleanStr),
|
|
790
|
-
isNumeric: RE_NUMERIC.test(cleanStr),
|
|
791
|
-
overrideMode,
|
|
792
|
-
negated: negated || undefined
|
|
793
|
-
};
|
|
658
|
+
const preparedTokens = prepareQueryTokens([searchTokenStr]);
|
|
659
|
+
if (preparedTokens.length === 0) {
|
|
660
|
+
return true;
|
|
661
|
+
}
|
|
662
|
+
const preparedToken = preparedTokens[0];
|
|
794
663
|
const matches = matchPreparedTokenInSortedList(preparedToken, targetTokens, opts);
|
|
795
|
-
return negated ? !matches : matches;
|
|
664
|
+
return preparedToken.negated ? !matches : matches;
|
|
796
665
|
}
|
|
797
666
|
function allPreparedTokensMatch(preparedTokens, targetTokens, opts) {
|
|
798
667
|
for (const preparedToken of preparedTokens) {
|
|
@@ -814,18 +683,7 @@ function allTokensMatchNumeric(searchTokenStrs, targetTokens, opts) {
|
|
|
814
683
|
|
|
815
684
|
// src/common/numeric/searchInData.ts
|
|
816
685
|
function searchInDataReturnIdsNumeric(query, metadata, opts) {
|
|
817
|
-
|
|
818
|
-
if (queryTokenStrs.length === 0) {
|
|
819
|
-
return [];
|
|
820
|
-
}
|
|
821
|
-
const preparedTokens = prepareQueryTokens(queryTokenStrs);
|
|
822
|
-
const results = [];
|
|
823
|
-
for (const [id, targetTokens] of metadata) {
|
|
824
|
-
if (allPreparedTokensMatch(preparedTokens, targetTokens, opts)) {
|
|
825
|
-
results.push(id);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
return results;
|
|
686
|
+
return searchInDataReturnIdsWithLimitNumeric(query, metadata, Infinity, opts);
|
|
829
687
|
}
|
|
830
688
|
function searchInDataReturnObjectsNumeric(query, metadata, data, opts) {
|
|
831
689
|
const ids = searchInDataReturnIdsNumeric(query, metadata, opts);
|
|
@@ -859,7 +717,7 @@ function searchInDataReturnIdsWithLimitNumeric(query, metadata, limit, opts) {
|
|
|
859
717
|
function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
860
718
|
const queryTokenStrs = prepareStringForSearch(query);
|
|
861
719
|
if (queryTokenStrs.length === 0) {
|
|
862
|
-
return { queryTokens: queryTokenStrs, results: [] };
|
|
720
|
+
return { queryTokens: queryTokenStrs, results: [], hasNegation: false };
|
|
863
721
|
}
|
|
864
722
|
const preparedTokens = prepareQueryTokens(queryTokenStrs);
|
|
865
723
|
const positiveTokens = preparedTokens.filter((t) => !t.negated);
|
|
@@ -957,258 +815,184 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
|
957
815
|
});
|
|
958
816
|
}
|
|
959
817
|
}
|
|
960
|
-
return { queryTokens: queryTokenStrs, results };
|
|
818
|
+
return { queryTokens: queryTokenStrs, results, hasNegation: negatedTokens.length > 0 };
|
|
961
819
|
}
|
|
962
820
|
function findInLinkedArraysSimpleNumeric(query, linked, limit = 10, opts) {
|
|
963
821
|
return findInLinkedArraysNumeric(query, linked, limit, opts).results;
|
|
964
822
|
}
|
|
965
|
-
// src/common/
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
823
|
+
// src/common/numeric/AugmentedMetadata.ts
|
|
824
|
+
class AugmentedMetadata {
|
|
825
|
+
baseMetadata;
|
|
826
|
+
augmentedTokens;
|
|
827
|
+
spec;
|
|
828
|
+
constructor(baseMetadata, spec, augmentedDataMap) {
|
|
829
|
+
this.baseMetadata = baseMetadata;
|
|
830
|
+
this.augmentedTokens = new Map;
|
|
831
|
+
this.spec = spec;
|
|
832
|
+
if (augmentedDataMap && augmentedDataMap.size > 0) {
|
|
833
|
+
this.updateAugmentedBatch(augmentedDataMap);
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
updateAugmented(id, augmentedData) {
|
|
837
|
+
if (!augmentedData) {
|
|
838
|
+
this.augmentedTokens.delete(id);
|
|
839
|
+
return;
|
|
974
840
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
primaryToLinked,
|
|
980
|
-
primaryData,
|
|
981
|
-
linkedData
|
|
982
|
-
};
|
|
983
|
-
}
|
|
984
|
-
// src/common/string/updateSearchMetadata.ts
|
|
985
|
-
function updateSearchMetadata(metadata, objectId, obj, spec) {
|
|
986
|
-
const tokens2 = obj != null ? prepareObjectForSearch(obj, spec) : undefined;
|
|
987
|
-
if (tokens2 === undefined) {
|
|
988
|
-
metadata.delete(objectId);
|
|
989
|
-
return false;
|
|
990
|
-
} else {
|
|
991
|
-
metadata.set(objectId, tokens2);
|
|
992
|
-
return true;
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
function updateSearchMetadataBatch(metadata, batch, spec) {
|
|
996
|
-
if (batch.length === 0) {
|
|
997
|
-
return { updated: 0, removed: 0 };
|
|
998
|
-
}
|
|
999
|
-
let updated = 0;
|
|
1000
|
-
let removed = 0;
|
|
1001
|
-
for (const { objectId, obj } of batch) {
|
|
1002
|
-
const wasUpdated = updateSearchMetadata(metadata, objectId, obj, spec);
|
|
1003
|
-
if (wasUpdated) {
|
|
1004
|
-
updated++;
|
|
841
|
+
const tokensMap = createTokensMap();
|
|
842
|
+
const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
843
|
+
if (tokens2 && tokens2.length > 0) {
|
|
844
|
+
this.augmentedTokens.set(id, tokens2);
|
|
1005
845
|
} else {
|
|
1006
|
-
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
return { updated, removed };
|
|
1010
|
-
}
|
|
1011
|
-
function removeFromSearchMetadata(metadata, objectId) {
|
|
1012
|
-
return metadata.delete(objectId);
|
|
1013
|
-
}
|
|
1014
|
-
function removeFromSearchMetadataBatch(metadata, objectIds) {
|
|
1015
|
-
if (objectIds.length === 0) {
|
|
1016
|
-
return 0;
|
|
1017
|
-
}
|
|
1018
|
-
let removed = 0;
|
|
1019
|
-
for (const id of objectIds) {
|
|
1020
|
-
if (metadata.delete(id)) {
|
|
1021
|
-
removed++;
|
|
846
|
+
this.augmentedTokens.delete(id);
|
|
1022
847
|
}
|
|
848
|
+
clearTokensMap(tokensMap);
|
|
1023
849
|
}
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
">": "end",
|
|
1031
|
-
"+": "startEnd",
|
|
1032
|
-
"*": "anywhere",
|
|
1033
|
-
"!": "whole"
|
|
1034
|
-
};
|
|
1035
|
-
function matchWithMode(searchToken, targetToken, mode) {
|
|
1036
|
-
switch (mode) {
|
|
1037
|
-
case "start":
|
|
1038
|
-
return targetToken.startsWith(searchToken);
|
|
1039
|
-
case "end":
|
|
1040
|
-
return targetToken.endsWith(searchToken);
|
|
1041
|
-
case "startEnd":
|
|
1042
|
-
return targetToken.startsWith(searchToken) || targetToken.endsWith(searchToken);
|
|
1043
|
-
case "anywhere":
|
|
1044
|
-
return targetToken.includes(searchToken);
|
|
1045
|
-
case "whole":
|
|
1046
|
-
return targetToken === searchToken;
|
|
1047
|
-
}
|
|
1048
|
-
}
|
|
1049
|
-
function matchToken(searchToken, targetToken, opts) {
|
|
1050
|
-
const firstChar = targetToken[0];
|
|
1051
|
-
const prefixMode = firstChar ? PREFIX_TO_MODE[firstChar] : undefined;
|
|
1052
|
-
if (prefixMode) {
|
|
1053
|
-
const actualTarget = targetToken.slice(1);
|
|
1054
|
-
return matchWithMode(searchToken, actualTarget, prefixMode);
|
|
1055
|
-
}
|
|
1056
|
-
const matchWords = opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
|
|
1057
|
-
const matchNumbers = opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers;
|
|
1058
|
-
const isNumeric = RE_NUMERIC2.test(searchToken);
|
|
1059
|
-
return matchWithMode(searchToken, targetToken, isNumeric ? matchNumbers : matchWords);
|
|
1060
|
-
}
|
|
1061
|
-
function matchTokenInSortedList(searchToken, targetTokens, opts) {
|
|
1062
|
-
const isNumeric = RE_NUMERIC2.test(searchToken);
|
|
1063
|
-
const effectiveMode = isNumeric ? opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers : opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
|
|
1064
|
-
const canEarlyExit = effectiveMode === "start";
|
|
1065
|
-
for (const targetToken of targetTokens) {
|
|
1066
|
-
const firstChar = targetToken[0];
|
|
1067
|
-
const hasPrefix = firstChar ? PREFIX_TO_MODE[firstChar] !== undefined : false;
|
|
1068
|
-
if (hasPrefix) {
|
|
1069
|
-
if (matchToken(searchToken, targetToken, opts)) {
|
|
1070
|
-
return true;
|
|
850
|
+
updateAugmentedBatch(augmentedDataMap) {
|
|
851
|
+
const tokensMap = createTokensMap();
|
|
852
|
+
for (const [id, augmentedData] of augmentedDataMap) {
|
|
853
|
+
if (!augmentedData) {
|
|
854
|
+
this.augmentedTokens.delete(id);
|
|
855
|
+
continue;
|
|
1071
856
|
}
|
|
1072
|
-
|
|
1073
|
-
if (
|
|
1074
|
-
|
|
1075
|
-
return true;
|
|
1076
|
-
}
|
|
1077
|
-
if (targetToken > searchToken && targetToken[0] !== searchToken[0]) {
|
|
1078
|
-
return false;
|
|
1079
|
-
}
|
|
857
|
+
const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
858
|
+
if (tokens2 && tokens2.length > 0) {
|
|
859
|
+
this.augmentedTokens.set(id, tokens2);
|
|
1080
860
|
} else {
|
|
1081
|
-
|
|
1082
|
-
return true;
|
|
1083
|
-
}
|
|
861
|
+
this.augmentedTokens.delete(id);
|
|
1084
862
|
}
|
|
1085
863
|
}
|
|
864
|
+
clearTokensMap(tokensMap);
|
|
1086
865
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
function allTokensMatch(searchTokens, targetTokens, opts) {
|
|
1090
|
-
for (const searchToken of searchTokens) {
|
|
1091
|
-
if (!matchTokenInSortedList(searchToken, targetTokens, opts)) {
|
|
1092
|
-
return false;
|
|
1093
|
-
}
|
|
866
|
+
clearAugmented(id) {
|
|
867
|
+
this.augmentedTokens.delete(id);
|
|
1094
868
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
869
|
+
clearAllAugmented() {
|
|
870
|
+
this.augmentedTokens.clear();
|
|
871
|
+
}
|
|
872
|
+
get(id) {
|
|
873
|
+
const baseTokens = this.baseMetadata.get(id);
|
|
874
|
+
if (!baseTokens)
|
|
875
|
+
return;
|
|
876
|
+
const augTokens = this.augmentedTokens.get(id);
|
|
877
|
+
if (!augTokens)
|
|
878
|
+
return baseTokens;
|
|
879
|
+
return this.mergeSortedTokenArrays(baseTokens, augTokens);
|
|
880
|
+
}
|
|
881
|
+
has(id) {
|
|
882
|
+
return this.baseMetadata.has(id);
|
|
883
|
+
}
|
|
884
|
+
get size() {
|
|
885
|
+
return this.baseMetadata.size;
|
|
886
|
+
}
|
|
887
|
+
[Symbol.iterator]() {
|
|
888
|
+
const self = this;
|
|
889
|
+
const baseIterator = this.baseMetadata[Symbol.iterator]();
|
|
1102
890
|
return {
|
|
1103
|
-
|
|
1104
|
-
|
|
891
|
+
next() {
|
|
892
|
+
const baseResult = baseIterator.next();
|
|
893
|
+
if (baseResult.done) {
|
|
894
|
+
return { done: true, value: undefined };
|
|
895
|
+
}
|
|
896
|
+
const [id, baseTokens] = baseResult.value;
|
|
897
|
+
const augTokens = self.augmentedTokens.get(id);
|
|
898
|
+
const tokens2 = augTokens ? self.mergeSortedTokenArrays(baseTokens, augTokens) : baseTokens;
|
|
899
|
+
return { done: false, value: [id, tokens2] };
|
|
900
|
+
},
|
|
901
|
+
[Symbol.iterator]() {
|
|
902
|
+
return this;
|
|
903
|
+
},
|
|
904
|
+
[Symbol.dispose]() {}
|
|
1105
905
|
};
|
|
1106
906
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
if (results.length >= limit) {
|
|
1110
|
-
break;
|
|
1111
|
-
}
|
|
1112
|
-
if (allTokensMatch(queryTokens, itemTokens, opts)) {
|
|
1113
|
-
const item = data.get(id);
|
|
1114
|
-
if (item) {
|
|
1115
|
-
results.push({
|
|
1116
|
-
item,
|
|
1117
|
-
tokens: itemTokens
|
|
1118
|
-
});
|
|
1119
|
-
}
|
|
1120
|
-
}
|
|
907
|
+
keys() {
|
|
908
|
+
return this.baseMetadata.keys();
|
|
1121
909
|
}
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
910
|
+
values() {
|
|
911
|
+
const self = this;
|
|
912
|
+
const keysIterator = this.baseMetadata.keys();
|
|
913
|
+
return {
|
|
914
|
+
next() {
|
|
915
|
+
const keyResult = keysIterator.next();
|
|
916
|
+
if (keyResult.done) {
|
|
917
|
+
return { done: true, value: undefined };
|
|
918
|
+
}
|
|
919
|
+
const tokens2 = self.get(keyResult.value);
|
|
920
|
+
return tokens2 ? { done: false, value: tokens2 } : { done: true, value: undefined };
|
|
921
|
+
},
|
|
922
|
+
[Symbol.iterator]() {
|
|
923
|
+
return this;
|
|
924
|
+
},
|
|
925
|
+
[Symbol.dispose]() {}
|
|
926
|
+
};
|
|
1131
927
|
}
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
results.push(id);
|
|
928
|
+
entries() {
|
|
929
|
+
return this[Symbol.iterator]();
|
|
930
|
+
}
|
|
931
|
+
forEach(callbackfn) {
|
|
932
|
+
for (const [id, tokens2] of this) {
|
|
933
|
+
callbackfn(tokens2, id, this);
|
|
1139
934
|
}
|
|
1140
935
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
// src/common/findInArray.ts
|
|
1145
|
-
function findInArray(query, data, metadata, limit = 10, opts) {
|
|
1146
|
-
const result = findInArrayReturnDataAndMeta(query, data, metadata, limit, opts);
|
|
1147
|
-
return result.results.map((r) => r.item);
|
|
1148
|
-
}
|
|
1149
|
-
// src/common/findInLinkedArrays.ts
|
|
1150
|
-
function findInLinkedArrays(query, linked, limit = 10, opts) {
|
|
1151
|
-
const queryTokens = prepareStringForSearch(query);
|
|
1152
|
-
if (queryTokens.length === 0) {
|
|
1153
|
-
return { queryTokens, results: [] };
|
|
936
|
+
set(_key, _value) {
|
|
937
|
+
throw new Error("AugmentedMetadata.set() is not supported. Use updateAugmented() instead.");
|
|
1154
938
|
}
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
const tokensMatchingPrimary = new Set;
|
|
1176
|
-
for (const queryToken of queryTokens) {
|
|
1177
|
-
if (matchTokenInSortedList(queryToken, primaryTokens, opts)) {
|
|
1178
|
-
anyMatchInPrimary = true;
|
|
1179
|
-
tokensMatchingPrimary.add(queryToken);
|
|
939
|
+
delete(_key) {
|
|
940
|
+
throw new Error("AugmentedMetadata.delete() is not supported. Use clearAugmented() instead.");
|
|
941
|
+
}
|
|
942
|
+
clear() {
|
|
943
|
+
throw new Error("AugmentedMetadata.clear() is not supported. Use clearAllAugmented() instead.");
|
|
944
|
+
}
|
|
945
|
+
get [Symbol.toStringTag]() {
|
|
946
|
+
return "AugmentedMetadata";
|
|
947
|
+
}
|
|
948
|
+
mergeSortedTokenArrays(a, b) {
|
|
949
|
+
const merged = new Uint32Array(a.length + b.length);
|
|
950
|
+
let i = 0, j = 0, k = 0;
|
|
951
|
+
let lastToken = -1;
|
|
952
|
+
while (i < a.length && j < b.length) {
|
|
953
|
+
const tokenA = a[i];
|
|
954
|
+
const tokenB = b[j];
|
|
955
|
+
if (tokenA < tokenB) {
|
|
956
|
+
if (tokenA !== lastToken) {
|
|
957
|
+
merged[k++] = tokenA;
|
|
958
|
+
lastToken = tokenA;
|
|
1180
959
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
}
|
|
960
|
+
i++;
|
|
961
|
+
} else if (tokenA > tokenB) {
|
|
962
|
+
if (tokenB !== lastToken) {
|
|
963
|
+
merged[k++] = tokenB;
|
|
964
|
+
lastToken = tokenB;
|
|
965
|
+
}
|
|
966
|
+
j++;
|
|
967
|
+
} else {
|
|
968
|
+
if (tokenA !== lastToken) {
|
|
969
|
+
merged[k++] = tokenA;
|
|
970
|
+
lastToken = tokenA;
|
|
1193
971
|
}
|
|
972
|
+
i++;
|
|
973
|
+
j++;
|
|
1194
974
|
}
|
|
1195
|
-
|
|
1196
|
-
|
|
975
|
+
}
|
|
976
|
+
while (i < a.length) {
|
|
977
|
+
const tokenA = a[i];
|
|
978
|
+
if (tokenA !== lastToken) {
|
|
979
|
+
merged[k++] = tokenA;
|
|
980
|
+
lastToken = tokenA;
|
|
1197
981
|
}
|
|
1198
|
-
|
|
1199
|
-
results.push({
|
|
1200
|
-
primary,
|
|
1201
|
-
linked: matchedLinked,
|
|
1202
|
-
matchedIn: anyMatchInPrimary && anyMatchInLinked ? "both" : anyMatchInPrimary ? "primary" : "linked"
|
|
1203
|
-
});
|
|
982
|
+
i++;
|
|
1204
983
|
}
|
|
984
|
+
while (j < b.length) {
|
|
985
|
+
const tokenB = b[j];
|
|
986
|
+
if (tokenB !== lastToken) {
|
|
987
|
+
merged[k++] = tokenB;
|
|
988
|
+
lastToken = tokenB;
|
|
989
|
+
}
|
|
990
|
+
j++;
|
|
991
|
+
}
|
|
992
|
+
return merged.slice(0, k);
|
|
1205
993
|
}
|
|
1206
|
-
return { queryTokens, results };
|
|
1207
|
-
}
|
|
1208
|
-
function findInLinkedArraysSimple(query, linked, limit = 10, opts) {
|
|
1209
|
-
return findInLinkedArrays(query, linked, limit, opts).results;
|
|
1210
994
|
}
|
|
1211
|
-
// src/common/syncSearchArrayMetadata.ts
|
|
995
|
+
// src/common/numeric/syncSearchArrayMetadata.ts
|
|
1212
996
|
function tokensEqual(a, b) {
|
|
1213
997
|
if (a.length !== b.length)
|
|
1214
998
|
return false;
|
|
@@ -1218,7 +1002,7 @@ function tokensEqual(a, b) {
|
|
|
1218
1002
|
}
|
|
1219
1003
|
return true;
|
|
1220
1004
|
}
|
|
1221
|
-
function
|
|
1005
|
+
function syncSearchArrayMetadataNumeric(metadata, newData, spec) {
|
|
1222
1006
|
const result = {
|
|
1223
1007
|
added: 0,
|
|
1224
1008
|
updated: 0,
|
|
@@ -1227,6 +1011,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
|
|
|
1227
1011
|
updatedIds: [],
|
|
1228
1012
|
removedIds: []
|
|
1229
1013
|
};
|
|
1014
|
+
const tokensMap = createTokensMap();
|
|
1230
1015
|
for (const id of metadata.keys()) {
|
|
1231
1016
|
if (!newData.has(id)) {
|
|
1232
1017
|
metadata.delete(id);
|
|
@@ -1235,7 +1020,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
|
|
|
1235
1020
|
}
|
|
1236
1021
|
}
|
|
1237
1022
|
for (const [id, item] of newData) {
|
|
1238
|
-
const newTokens =
|
|
1023
|
+
const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1239
1024
|
if (newTokens === undefined) {
|
|
1240
1025
|
if (metadata.has(id)) {
|
|
1241
1026
|
metadata.delete(id);
|
|
@@ -1255,9 +1040,10 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
|
|
|
1255
1040
|
result.updatedIds.push(id);
|
|
1256
1041
|
}
|
|
1257
1042
|
}
|
|
1043
|
+
clearTokensMap(tokensMap);
|
|
1258
1044
|
return result;
|
|
1259
1045
|
}
|
|
1260
|
-
function
|
|
1046
|
+
function syncSearchArrayMetadataNumericWithPrevious(metadata, previousData, newData, options, spec) {
|
|
1261
1047
|
const result = {
|
|
1262
1048
|
added: 0,
|
|
1263
1049
|
updated: 0,
|
|
@@ -1266,6 +1052,7 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
|
|
|
1266
1052
|
updatedIds: [],
|
|
1267
1053
|
removedIds: []
|
|
1268
1054
|
};
|
|
1055
|
+
const tokensMap = createTokensMap();
|
|
1269
1056
|
for (const id of previousData.keys()) {
|
|
1270
1057
|
if (!newData.has(id)) {
|
|
1271
1058
|
metadata.delete(id);
|
|
@@ -1276,14 +1063,14 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
|
|
|
1276
1063
|
for (const [id, item] of newData) {
|
|
1277
1064
|
const wasInPrevious = previousData.has(id);
|
|
1278
1065
|
if (!wasInPrevious) {
|
|
1279
|
-
const tokens2 =
|
|
1066
|
+
const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1280
1067
|
if (tokens2 !== undefined) {
|
|
1281
1068
|
metadata.set(id, tokens2);
|
|
1282
1069
|
result.added++;
|
|
1283
1070
|
result.addedIds.push(id);
|
|
1284
1071
|
}
|
|
1285
1072
|
} else if (!options?.skipUpdateCheck) {
|
|
1286
|
-
const newTokens =
|
|
1073
|
+
const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1287
1074
|
if (newTokens === undefined) {
|
|
1288
1075
|
metadata.delete(id);
|
|
1289
1076
|
result.removed++;
|
|
@@ -1298,9 +1085,10 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
|
|
|
1298
1085
|
}
|
|
1299
1086
|
}
|
|
1300
1087
|
}
|
|
1088
|
+
clearTokensMap(tokensMap);
|
|
1301
1089
|
return result;
|
|
1302
1090
|
}
|
|
1303
|
-
// src/common/updateSearchLinkedMetadata.ts
|
|
1091
|
+
// src/common/numeric/updateSearchLinkedMetadata.ts
|
|
1304
1092
|
function tokensEqual2(a, b) {
|
|
1305
1093
|
if (a.length !== b.length)
|
|
1306
1094
|
return false;
|
|
@@ -1310,11 +1098,13 @@ function tokensEqual2(a, b) {
|
|
|
1310
1098
|
}
|
|
1311
1099
|
return true;
|
|
1312
1100
|
}
|
|
1313
|
-
function
|
|
1101
|
+
function upsertPrimaryItemNumeric(linked, item, spec) {
|
|
1314
1102
|
const id = item._id;
|
|
1315
1103
|
const wasAdded = !linked.primaryData.has(id);
|
|
1316
1104
|
linked.primaryData.set(id, item);
|
|
1317
|
-
const
|
|
1105
|
+
const tokensMap = createTokensMap();
|
|
1106
|
+
const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1107
|
+
clearTokensMap(tokensMap);
|
|
1318
1108
|
if (tokens2 !== undefined) {
|
|
1319
1109
|
linked.primaryMeta.set(id, tokens2);
|
|
1320
1110
|
} else {
|
|
@@ -1325,7 +1115,7 @@ function upsertPrimaryItem(linked, item, spec) {
|
|
|
1325
1115
|
}
|
|
1326
1116
|
return { added: wasAdded };
|
|
1327
1117
|
}
|
|
1328
|
-
function
|
|
1118
|
+
function removePrimaryItemNumeric(linked, primaryId) {
|
|
1329
1119
|
if (!linked.primaryData.has(primaryId)) {
|
|
1330
1120
|
return false;
|
|
1331
1121
|
}
|
|
@@ -1334,7 +1124,7 @@ function removePrimaryItem(linked, primaryId) {
|
|
|
1334
1124
|
linked.primaryToLinked.delete(primaryId);
|
|
1335
1125
|
return true;
|
|
1336
1126
|
}
|
|
1337
|
-
function
|
|
1127
|
+
function upsertLinkedItemNumeric(linked, item, foreignKeyGetter, spec) {
|
|
1338
1128
|
const id = item._id;
|
|
1339
1129
|
const newPrimaryId = foreignKeyGetter(item);
|
|
1340
1130
|
let previousPrimaryId;
|
|
@@ -1344,7 +1134,9 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
|
|
|
1344
1134
|
}
|
|
1345
1135
|
const wasAdded = !existingItem;
|
|
1346
1136
|
linked.linkedData.set(id, item);
|
|
1347
|
-
const
|
|
1137
|
+
const tokensMap = createTokensMap();
|
|
1138
|
+
const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1139
|
+
clearTokensMap(tokensMap);
|
|
1348
1140
|
if (tokens2 !== undefined) {
|
|
1349
1141
|
linked.linkedMeta.set(id, tokens2);
|
|
1350
1142
|
} else {
|
|
@@ -1376,7 +1168,7 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
|
|
|
1376
1168
|
previousPrimaryId: wasAdded ? undefined : previousPrimaryId
|
|
1377
1169
|
};
|
|
1378
1170
|
}
|
|
1379
|
-
function
|
|
1171
|
+
function removeLinkedItemNumeric(linked, linkedId, foreignKeyGetter) {
|
|
1380
1172
|
const existingItem = linked.linkedData.get(linkedId);
|
|
1381
1173
|
if (!existingItem) {
|
|
1382
1174
|
return false;
|
|
@@ -1395,12 +1187,13 @@ function removeLinkedItem(linked, linkedId, foreignKeyGetter) {
|
|
|
1395
1187
|
}
|
|
1396
1188
|
return true;
|
|
1397
1189
|
}
|
|
1398
|
-
function
|
|
1190
|
+
function syncLinkedItemsForPrimaryNumeric(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
|
|
1399
1191
|
const result = {
|
|
1400
1192
|
added: 0,
|
|
1401
1193
|
updated: 0,
|
|
1402
1194
|
removed: 0
|
|
1403
1195
|
};
|
|
1196
|
+
const tokensMap = createTokensMap();
|
|
1404
1197
|
const currentLinkedIds = new Set(linked.primaryToLinked.get(primaryId) || []);
|
|
1405
1198
|
const newLinkedIds = new Set;
|
|
1406
1199
|
for (const [id, item] of newLinkedItems) {
|
|
@@ -1420,7 +1213,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
|
|
|
1420
1213
|
}
|
|
1421
1214
|
for (const id of newLinkedIds) {
|
|
1422
1215
|
const item = newLinkedItems.get(id);
|
|
1423
|
-
const tokens2 =
|
|
1216
|
+
const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1424
1217
|
if (currentLinkedIds.has(id)) {
|
|
1425
1218
|
const existingTokens = linked.linkedMeta.get(id);
|
|
1426
1219
|
if (tokens2 !== undefined) {
|
|
@@ -1439,6 +1232,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
|
|
|
1439
1232
|
}
|
|
1440
1233
|
}
|
|
1441
1234
|
linked.primaryToLinked.set(primaryId, Array.from(newLinkedIds));
|
|
1235
|
+
clearTokensMap(tokensMap);
|
|
1442
1236
|
return result;
|
|
1443
1237
|
}
|
|
1444
1238
|
// src/common/SearchUniverse.ts
|
|
@@ -1675,7 +1469,7 @@ class SearchUniverse {
|
|
|
1675
1469
|
const linkedSearchResults = findInLinkedArraysNumeric(query, linkedMetadata, limit, searchOpts);
|
|
1676
1470
|
if (linkedSearchResults.results.length > 0) {
|
|
1677
1471
|
const combinedResults = [];
|
|
1678
|
-
const hasNegation =
|
|
1472
|
+
const hasNegation = linkedSearchResults.hasNegation;
|
|
1679
1473
|
for (const result of linkedSearchResults.results) {
|
|
1680
1474
|
let linkedItems = result.linked;
|
|
1681
1475
|
if (result.matchedIn === "primary" && !hasNegation) {
|
|
@@ -1722,19 +1516,15 @@ class SearchUniverse {
|
|
|
1722
1516
|
}
|
|
1723
1517
|
}
|
|
1724
1518
|
export {
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
upsertLinkedItem,
|
|
1728
|
-
updateSearchMetadata as updateSearchMetadataString,
|
|
1729
|
-
updateSearchMetadataBatch as updateSearchMetadataBatchString,
|
|
1519
|
+
upsertPrimaryItemNumeric as upsertPrimaryItem,
|
|
1520
|
+
upsertLinkedItemNumeric as upsertLinkedItem,
|
|
1730
1521
|
updateSearchMetadataBatchNumeric as updateSearchMetadataBatch,
|
|
1731
1522
|
updateSearchMetadataNumeric as updateSearchMetadata,
|
|
1732
|
-
unwrapMetadataLegacy,
|
|
1733
1523
|
tokens,
|
|
1734
1524
|
tokenize,
|
|
1735
|
-
syncSearchArrayMetadataWithPrevious,
|
|
1736
|
-
syncSearchArrayMetadata,
|
|
1737
|
-
syncLinkedItemsForPrimary,
|
|
1525
|
+
syncSearchArrayMetadataNumericWithPrevious as syncSearchArrayMetadataWithPrevious,
|
|
1526
|
+
syncSearchArrayMetadataNumeric as syncSearchArrayMetadata,
|
|
1527
|
+
syncLinkedItemsForPrimaryNumeric as syncLinkedItemsForPrimary,
|
|
1738
1528
|
searchableDataToArray,
|
|
1739
1529
|
searchInDataReturnIdsWithLimitNumeric as searchInDataWithLimit,
|
|
1740
1530
|
searchInDataReturnObjectsNumeric as searchInDataReturnObjects,
|
|
@@ -1742,22 +1532,17 @@ export {
|
|
|
1742
1532
|
searchInDataReturnIdsNumeric as searchInData,
|
|
1743
1533
|
sanitiseString,
|
|
1744
1534
|
resetTokenRegistry,
|
|
1745
|
-
removePrimaryItem,
|
|
1746
|
-
removeLinkedItem,
|
|
1747
|
-
removeFromSearchMetadata as removeFromSearchMetadataString,
|
|
1748
|
-
removeFromSearchMetadataBatch as removeFromSearchMetadataBatchString,
|
|
1535
|
+
removePrimaryItemNumeric as removePrimaryItem,
|
|
1536
|
+
removeLinkedItemNumeric as removeLinkedItem,
|
|
1749
1537
|
removeFromSearchMetadataBatchNumeric as removeFromSearchMetadataBatch,
|
|
1750
1538
|
removeFromSearchMetadataNumeric as removeFromSearchMetadata,
|
|
1751
1539
|
registerToken,
|
|
1752
1540
|
preprocessString,
|
|
1753
1541
|
prepareStringForSearch,
|
|
1754
1542
|
prepareQueryTokens,
|
|
1755
|
-
prepareObjectForSearch as prepareObjectForSearchString,
|
|
1756
1543
|
prepareObjectForSearchNumeric as prepareObjectForSearch,
|
|
1757
1544
|
normalizeDates,
|
|
1758
1545
|
matchTokenInSortedListNumeric,
|
|
1759
|
-
matchTokenInSortedList,
|
|
1760
|
-
matchToken,
|
|
1761
1546
|
matchPreparedTokenInSortedList,
|
|
1762
1547
|
isDeletedOrBlocked,
|
|
1763
1548
|
getTokenCount,
|
|
@@ -1765,31 +1550,21 @@ export {
|
|
|
1765
1550
|
getOrCreateTokenId,
|
|
1766
1551
|
findTokenId,
|
|
1767
1552
|
findInLinkedArraysSimpleNumeric,
|
|
1768
|
-
findInLinkedArraysSimple,
|
|
1769
1553
|
findInLinkedArraysNumeric,
|
|
1770
|
-
findInLinkedArrays,
|
|
1771
|
-
findInArrayReturnIds,
|
|
1772
|
-
findInArrayReturnDataAndMeta,
|
|
1773
|
-
findInArray,
|
|
1774
|
-
extractSearchableStringDefault,
|
|
1775
1554
|
encodeTokenWithMode,
|
|
1776
1555
|
decodeTokenId,
|
|
1777
1556
|
decodeMatchMode,
|
|
1778
1557
|
createTokensMap,
|
|
1779
|
-
createSearchLinkedMetadata as createSearchLinkedMetadataString,
|
|
1780
1558
|
createSearchLinkedMetadataNumeric as createSearchLinkedMetadata,
|
|
1781
|
-
createSearchArrayMetadata as createSearchArrayMetadataString,
|
|
1782
1559
|
createSearchArrayMetadataNumeric as createSearchArrayMetadata,
|
|
1783
1560
|
clearTokensMap,
|
|
1784
1561
|
binarySearchUint32,
|
|
1785
1562
|
arrayToSearchableData,
|
|
1786
1563
|
allTokensMatchNumeric,
|
|
1787
|
-
allTokensMatch,
|
|
1788
1564
|
allPreparedTokensMatch,
|
|
1789
1565
|
TOKEN_ID_MASK,
|
|
1790
1566
|
SearchUniverse,
|
|
1791
|
-
PREFIX_TO_MATCH_MODE,
|
|
1792
|
-
MATCH_MODE_PREFIXES,
|
|
1793
1567
|
MATCH_MODE_BITS,
|
|
1794
|
-
DEFAULT_SEARCH_OPTS
|
|
1568
|
+
DEFAULT_SEARCH_OPTS,
|
|
1569
|
+
AugmentedMetadata
|
|
1795
1570
|
};
|