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.cjs
CHANGED
|
@@ -29,19 +29,15 @@ var __export = (target, all) => {
|
|
|
29
29
|
// src/index.ts
|
|
30
30
|
var exports_src = {};
|
|
31
31
|
__export(exports_src, {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
upsertLinkedItem: () => upsertLinkedItem,
|
|
35
|
-
updateSearchMetadataString: () => updateSearchMetadata,
|
|
36
|
-
updateSearchMetadataBatchString: () => updateSearchMetadataBatch,
|
|
32
|
+
upsertPrimaryItem: () => upsertPrimaryItemNumeric,
|
|
33
|
+
upsertLinkedItem: () => upsertLinkedItemNumeric,
|
|
37
34
|
updateSearchMetadataBatch: () => updateSearchMetadataBatchNumeric,
|
|
38
35
|
updateSearchMetadata: () => updateSearchMetadataNumeric,
|
|
39
|
-
unwrapMetadataLegacy: () => unwrapMetadataLegacy,
|
|
40
36
|
tokens: () => tokens,
|
|
41
37
|
tokenize: () => tokenize,
|
|
42
|
-
syncSearchArrayMetadataWithPrevious: () =>
|
|
43
|
-
syncSearchArrayMetadata: () =>
|
|
44
|
-
syncLinkedItemsForPrimary: () =>
|
|
38
|
+
syncSearchArrayMetadataWithPrevious: () => syncSearchArrayMetadataNumericWithPrevious,
|
|
39
|
+
syncSearchArrayMetadata: () => syncSearchArrayMetadataNumeric,
|
|
40
|
+
syncLinkedItemsForPrimary: () => syncLinkedItemsForPrimaryNumeric,
|
|
45
41
|
searchableDataToArray: () => searchableDataToArray,
|
|
46
42
|
searchInDataWithLimit: () => searchInDataReturnIdsWithLimitNumeric,
|
|
47
43
|
searchInDataReturnObjects: () => searchInDataReturnObjectsNumeric,
|
|
@@ -49,22 +45,17 @@ __export(exports_src, {
|
|
|
49
45
|
searchInData: () => searchInDataReturnIdsNumeric,
|
|
50
46
|
sanitiseString: () => sanitiseString,
|
|
51
47
|
resetTokenRegistry: () => resetTokenRegistry,
|
|
52
|
-
removePrimaryItem: () =>
|
|
53
|
-
removeLinkedItem: () =>
|
|
54
|
-
removeFromSearchMetadataString: () => removeFromSearchMetadata,
|
|
55
|
-
removeFromSearchMetadataBatchString: () => removeFromSearchMetadataBatch,
|
|
48
|
+
removePrimaryItem: () => removePrimaryItemNumeric,
|
|
49
|
+
removeLinkedItem: () => removeLinkedItemNumeric,
|
|
56
50
|
removeFromSearchMetadataBatch: () => removeFromSearchMetadataBatchNumeric,
|
|
57
51
|
removeFromSearchMetadata: () => removeFromSearchMetadataNumeric,
|
|
58
52
|
registerToken: () => registerToken,
|
|
59
53
|
preprocessString: () => preprocessString,
|
|
60
54
|
prepareStringForSearch: () => prepareStringForSearch,
|
|
61
55
|
prepareQueryTokens: () => prepareQueryTokens,
|
|
62
|
-
prepareObjectForSearchString: () => prepareObjectForSearch,
|
|
63
56
|
prepareObjectForSearch: () => prepareObjectForSearchNumeric,
|
|
64
57
|
normalizeDates: () => normalizeDates,
|
|
65
58
|
matchTokenInSortedListNumeric: () => matchTokenInSortedListNumeric,
|
|
66
|
-
matchTokenInSortedList: () => matchTokenInSortedList,
|
|
67
|
-
matchToken: () => matchToken,
|
|
68
59
|
matchPreparedTokenInSortedList: () => matchPreparedTokenInSortedList,
|
|
69
60
|
isDeletedOrBlocked: () => isDeletedOrBlocked,
|
|
70
61
|
getTokenCount: () => getTokenCount,
|
|
@@ -72,40 +63,32 @@ __export(exports_src, {
|
|
|
72
63
|
getOrCreateTokenId: () => getOrCreateTokenId,
|
|
73
64
|
findTokenId: () => findTokenId,
|
|
74
65
|
findInLinkedArraysSimpleNumeric: () => findInLinkedArraysSimpleNumeric,
|
|
75
|
-
findInLinkedArraysSimple: () => findInLinkedArraysSimple,
|
|
76
66
|
findInLinkedArraysNumeric: () => findInLinkedArraysNumeric,
|
|
77
|
-
findInLinkedArrays: () => findInLinkedArrays,
|
|
78
|
-
findInArrayReturnIds: () => findInArrayReturnIds,
|
|
79
|
-
findInArrayReturnDataAndMeta: () => findInArrayReturnDataAndMeta,
|
|
80
|
-
findInArray: () => findInArray,
|
|
81
|
-
extractSearchableStringDefault: () => extractSearchableStringDefault,
|
|
82
67
|
encodeTokenWithMode: () => encodeTokenWithMode,
|
|
83
68
|
decodeTokenId: () => decodeTokenId,
|
|
84
69
|
decodeMatchMode: () => decodeMatchMode,
|
|
85
70
|
createTokensMap: () => createTokensMap,
|
|
86
|
-
createSearchLinkedMetadataString: () => createSearchLinkedMetadata,
|
|
87
71
|
createSearchLinkedMetadata: () => createSearchLinkedMetadataNumeric,
|
|
88
|
-
createSearchArrayMetadataString: () => createSearchArrayMetadata,
|
|
89
72
|
createSearchArrayMetadata: () => createSearchArrayMetadataNumeric,
|
|
90
73
|
clearTokensMap: () => clearTokensMap,
|
|
91
74
|
binarySearchUint32: () => binarySearchUint32,
|
|
92
75
|
arrayToSearchableData: () => arrayToSearchableData,
|
|
93
76
|
allTokensMatchNumeric: () => allTokensMatchNumeric,
|
|
94
|
-
allTokensMatch: () => allTokensMatch,
|
|
95
77
|
allPreparedTokensMatch: () => allPreparedTokensMatch,
|
|
96
78
|
TOKEN_ID_MASK: () => TOKEN_ID_MASK,
|
|
97
79
|
SearchUniverse: () => SearchUniverse,
|
|
98
|
-
PREFIX_TO_MATCH_MODE: () => PREFIX_TO_MATCH_MODE,
|
|
99
|
-
MATCH_MODE_PREFIXES: () => MATCH_MODE_PREFIXES,
|
|
100
80
|
MATCH_MODE_BITS: () => MATCH_MODE_BITS,
|
|
101
|
-
DEFAULT_SEARCH_OPTS: () => DEFAULT_SEARCH_OPTS
|
|
81
|
+
DEFAULT_SEARCH_OPTS: () => DEFAULT_SEARCH_OPTS,
|
|
82
|
+
AugmentedMetadata: () => AugmentedMetadata
|
|
102
83
|
});
|
|
103
84
|
module.exports = __toCommonJS(exports_src);
|
|
104
85
|
|
|
105
86
|
// src/types/index.ts
|
|
106
87
|
var DEFAULT_SEARCH_OPTS = {
|
|
107
88
|
matchWords: "start",
|
|
108
|
-
matchNumbers: "startEnd"
|
|
89
|
+
matchNumbers: "startEnd",
|
|
90
|
+
matchNumbersShort: "whole",
|
|
91
|
+
matchNumbersThreshold: 6
|
|
109
92
|
};
|
|
110
93
|
function arrayToSearchableData(items) {
|
|
111
94
|
const map = new Map;
|
|
@@ -233,7 +216,7 @@ function preprocessString(input) {
|
|
|
233
216
|
|
|
234
217
|
// src/utils/sanitiseString.ts
|
|
235
218
|
var RE_DIACRITICS = /[\u0300-\u036f]/g;
|
|
236
|
-
var RE_INVALID_CHARS = /[^a-z0-9
|
|
219
|
+
var RE_INVALID_CHARS = /[^a-z0-9.\-~<>+*!=? ]/g;
|
|
237
220
|
function sanitiseString(input) {
|
|
238
221
|
let result = input;
|
|
239
222
|
result = result.toLowerCase();
|
|
@@ -277,11 +260,16 @@ function tokenize(input, config) {
|
|
|
277
260
|
let tokens = input.split(" ").map((token) => token.trim()).filter((token) => token.length > 0);
|
|
278
261
|
if (config?.replaceTokens) {
|
|
279
262
|
tokens = tokens.map((token) => {
|
|
280
|
-
if (token.startsWith("--")
|
|
263
|
+
if (token.length > 2 && token.startsWith("--")) {
|
|
281
264
|
const withoutPrefix = token.slice(2);
|
|
282
265
|
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
283
266
|
return replaced ? "--" + replaced : token;
|
|
284
267
|
}
|
|
268
|
+
if (token.length > 1 && token[0] === "-" && /^[a-z]/i.test(token[1])) {
|
|
269
|
+
const withoutPrefix = token.slice(1);
|
|
270
|
+
const replaced = config.replaceTokens.get(withoutPrefix);
|
|
271
|
+
return replaced ? "-" + replaced : token;
|
|
272
|
+
}
|
|
285
273
|
return config.replaceTokens.get(token) ?? token;
|
|
286
274
|
});
|
|
287
275
|
}
|
|
@@ -362,13 +350,6 @@ function prepareStringForSearchNumeric(input, tokensMap) {
|
|
|
362
350
|
}
|
|
363
351
|
|
|
364
352
|
// src/common/string/createSearchArrayMetadata.ts
|
|
365
|
-
var MATCH_MODE_PREFIXES = {
|
|
366
|
-
start: "<",
|
|
367
|
-
end: ">",
|
|
368
|
-
startEnd: "+",
|
|
369
|
-
anywhere: "*",
|
|
370
|
-
whole: "!"
|
|
371
|
-
};
|
|
372
353
|
var PREFIX_TO_MATCH_MODE = {
|
|
373
354
|
"<": "start",
|
|
374
355
|
">": "end",
|
|
@@ -379,155 +360,9 @@ var PREFIX_TO_MATCH_MODE = {
|
|
|
379
360
|
"?": "anywhere"
|
|
380
361
|
};
|
|
381
362
|
var DEFAULT_EXCLUDED_FIELDS = new Set(["_id", "_deleted", "_blocked"]);
|
|
382
|
-
function getValueByPath(obj, path) {
|
|
383
|
-
const parts = path.split(".");
|
|
384
|
-
let current = obj;
|
|
385
|
-
for (let i = 0;i < parts.length; i++) {
|
|
386
|
-
if (current == null)
|
|
387
|
-
return;
|
|
388
|
-
const part = parts[i];
|
|
389
|
-
if (Array.isArray(current)) {
|
|
390
|
-
const remainingPath = parts.slice(i).join(".");
|
|
391
|
-
const results = [];
|
|
392
|
-
for (const item of current) {
|
|
393
|
-
const value = getValueByPath(item, remainingPath);
|
|
394
|
-
if (value !== undefined) {
|
|
395
|
-
if (Array.isArray(value)) {
|
|
396
|
-
results.push(...value);
|
|
397
|
-
} else {
|
|
398
|
-
results.push(value);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
return results.length > 0 ? results : undefined;
|
|
403
|
-
}
|
|
404
|
-
if (typeof current === "object") {
|
|
405
|
-
current = current[part];
|
|
406
|
-
} else {
|
|
407
|
-
return;
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
return current;
|
|
411
|
-
}
|
|
412
|
-
function isDotNotation(field) {
|
|
413
|
-
return field.includes(".");
|
|
414
|
-
}
|
|
415
|
-
function getRootField(field) {
|
|
416
|
-
const dotIndex = field.indexOf(".");
|
|
417
|
-
return dotIndex === -1 ? field : field.slice(0, dotIndex);
|
|
418
|
-
}
|
|
419
|
-
function extractStringsFromValue(value, results) {
|
|
420
|
-
if (value == null)
|
|
421
|
-
return;
|
|
422
|
-
if (typeof value === "string") {
|
|
423
|
-
results.push(value);
|
|
424
|
-
} else if (typeof value === "number") {
|
|
425
|
-
results.push(String(value));
|
|
426
|
-
} else if (value instanceof Date) {
|
|
427
|
-
results.push(value.toISOString());
|
|
428
|
-
} else if (Array.isArray(value)) {
|
|
429
|
-
for (const item of value) {
|
|
430
|
-
extractStringsFromValue(item, results);
|
|
431
|
-
}
|
|
432
|
-
} else if (typeof value === "object") {
|
|
433
|
-
for (const v of Object.values(value)) {
|
|
434
|
-
extractStringsFromValue(v, results);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
363
|
function isDeletedOrBlocked(obj) {
|
|
439
364
|
return obj._deleted != null || obj._blocked != null;
|
|
440
365
|
}
|
|
441
|
-
function extractSearchableStringDefault(obj, spec) {
|
|
442
|
-
if (isDeletedOrBlocked(obj)) {
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
if (spec?.enrichSearchObjectFn) {
|
|
446
|
-
spec.enrichSearchObjectFn(obj, spec.searchContext);
|
|
447
|
-
}
|
|
448
|
-
const parts = [];
|
|
449
|
-
const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
|
|
450
|
-
const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
|
|
451
|
-
for (const key of fieldsToSearch) {
|
|
452
|
-
const keyStr = key;
|
|
453
|
-
if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
|
|
454
|
-
continue;
|
|
455
|
-
if (fieldsToExclude.has(key))
|
|
456
|
-
continue;
|
|
457
|
-
const value = isDotNotation(keyStr) ? getValueByPath(obj, keyStr) : obj[key];
|
|
458
|
-
extractStringsFromValue(value, parts);
|
|
459
|
-
}
|
|
460
|
-
return parts.join(" ");
|
|
461
|
-
}
|
|
462
|
-
function prepareObjectForSearch(obj, spec) {
|
|
463
|
-
if (isDeletedOrBlocked(obj)) {
|
|
464
|
-
return;
|
|
465
|
-
}
|
|
466
|
-
if (spec?.extractSearchableStringFn) {
|
|
467
|
-
const searchableString = spec.extractSearchableStringFn(obj);
|
|
468
|
-
if (searchableString === undefined) {
|
|
469
|
-
return;
|
|
470
|
-
}
|
|
471
|
-
return prepareStringForSearch(searchableString);
|
|
472
|
-
}
|
|
473
|
-
return prepareObjectFieldsForSearch(obj, spec);
|
|
474
|
-
}
|
|
475
|
-
function prepareObjectFieldsForSearch(obj, spec) {
|
|
476
|
-
if (spec?.enrichSearchObjectFn) {
|
|
477
|
-
spec.enrichSearchObjectFn(obj, spec.searchContext);
|
|
478
|
-
}
|
|
479
|
-
const allTokens = [];
|
|
480
|
-
const fieldMatchModes = spec?.fieldMatchModes;
|
|
481
|
-
const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
|
|
482
|
-
const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
|
|
483
|
-
const processedRootFields = new Set;
|
|
484
|
-
for (const key of fieldsToSearch) {
|
|
485
|
-
const keyStr = key;
|
|
486
|
-
if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
|
|
487
|
-
continue;
|
|
488
|
-
if (fieldsToExclude.has(key))
|
|
489
|
-
continue;
|
|
490
|
-
const isDot = isDotNotation(keyStr);
|
|
491
|
-
const rootField = getRootField(keyStr);
|
|
492
|
-
let value;
|
|
493
|
-
if (isDot) {
|
|
494
|
-
value = getValueByPath(obj, keyStr);
|
|
495
|
-
} else {
|
|
496
|
-
value = obj[key];
|
|
497
|
-
processedRootFields.add(rootField);
|
|
498
|
-
}
|
|
499
|
-
if (value == null)
|
|
500
|
-
continue;
|
|
501
|
-
const matchMode = fieldMatchModes?.[key];
|
|
502
|
-
const prefix = matchMode ? MATCH_MODE_PREFIXES[matchMode] : "";
|
|
503
|
-
const fieldStrings = [];
|
|
504
|
-
extractStringsFromValue(value, fieldStrings);
|
|
505
|
-
if (fieldStrings.length > 0) {
|
|
506
|
-
const fieldText = fieldStrings.join(" ");
|
|
507
|
-
const tokens2 = prepareStringForSearch(fieldText);
|
|
508
|
-
for (const token of tokens2) {
|
|
509
|
-
allTokens.push(prefix + token);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
return [...new Set(allTokens)].sort();
|
|
514
|
-
}
|
|
515
|
-
function createSearchArrayMetadata(data, spec) {
|
|
516
|
-
const metadata = new Map;
|
|
517
|
-
for (const [id, item] of data) {
|
|
518
|
-
const tokens2 = prepareObjectForSearch(item, spec);
|
|
519
|
-
if (tokens2 !== undefined) {
|
|
520
|
-
metadata.set(id, tokens2);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
return metadata;
|
|
524
|
-
}
|
|
525
|
-
function wrapMetadataLegacy(metadata) {
|
|
526
|
-
return { items: metadata };
|
|
527
|
-
}
|
|
528
|
-
function unwrapMetadataLegacy(legacy) {
|
|
529
|
-
return legacy.items;
|
|
530
|
-
}
|
|
531
366
|
|
|
532
367
|
// src/common/numeric/createSearchArrayMetadata.ts
|
|
533
368
|
var MATCH_MODE_BITS = {
|
|
@@ -561,7 +396,7 @@ function decodeMatchMode(encoded) {
|
|
|
561
396
|
}
|
|
562
397
|
}
|
|
563
398
|
var DEFAULT_EXCLUDED_FIELDS2 = new Set(["_id", "_deleted", "_blocked"]);
|
|
564
|
-
function
|
|
399
|
+
function getValueByPath(obj, path) {
|
|
565
400
|
const parts = path.split(".");
|
|
566
401
|
let current = obj;
|
|
567
402
|
for (let i = 0;i < parts.length; i++) {
|
|
@@ -572,7 +407,7 @@ function getValueByPath2(obj, path) {
|
|
|
572
407
|
const remainingPath = parts.slice(i).join(".");
|
|
573
408
|
const results = [];
|
|
574
409
|
for (const item of current) {
|
|
575
|
-
const value =
|
|
410
|
+
const value = getValueByPath(item, remainingPath);
|
|
576
411
|
if (value !== undefined) {
|
|
577
412
|
if (Array.isArray(value)) {
|
|
578
413
|
results.push(...value);
|
|
@@ -591,10 +426,10 @@ function getValueByPath2(obj, path) {
|
|
|
591
426
|
}
|
|
592
427
|
return current;
|
|
593
428
|
}
|
|
594
|
-
function
|
|
429
|
+
function isDotNotation(field) {
|
|
595
430
|
return field.includes(".");
|
|
596
431
|
}
|
|
597
|
-
function
|
|
432
|
+
function extractStringsFromValue(value, results) {
|
|
598
433
|
if (value == null)
|
|
599
434
|
return;
|
|
600
435
|
if (typeof value === "string") {
|
|
@@ -605,11 +440,11 @@ function extractStringsFromValue2(value, results) {
|
|
|
605
440
|
results.push(value.toISOString());
|
|
606
441
|
} else if (Array.isArray(value)) {
|
|
607
442
|
for (const item of value) {
|
|
608
|
-
|
|
443
|
+
extractStringsFromValue(item, results);
|
|
609
444
|
}
|
|
610
445
|
} else if (typeof value === "object") {
|
|
611
446
|
for (const v of Object.values(value)) {
|
|
612
|
-
|
|
447
|
+
extractStringsFromValue(v, results);
|
|
613
448
|
}
|
|
614
449
|
}
|
|
615
450
|
}
|
|
@@ -640,13 +475,13 @@ function prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap) {
|
|
|
640
475
|
continue;
|
|
641
476
|
if (fieldsToExclude.has(key))
|
|
642
477
|
continue;
|
|
643
|
-
const isDot =
|
|
644
|
-
const value = isDot ?
|
|
478
|
+
const isDot = isDotNotation(keyStr);
|
|
479
|
+
const value = isDot ? getValueByPath(obj, keyStr) : obj[key];
|
|
645
480
|
if (value == null)
|
|
646
481
|
continue;
|
|
647
482
|
const matchMode = fieldMatchModes?.[key];
|
|
648
483
|
const fieldStrings = [];
|
|
649
|
-
|
|
484
|
+
extractStringsFromValue(value, fieldStrings);
|
|
650
485
|
if (fieldStrings.length > 0) {
|
|
651
486
|
const fieldText = fieldStrings.join(" ");
|
|
652
487
|
const datesNormalized = normalizeDates(fieldText);
|
|
@@ -750,14 +585,38 @@ function removeFromSearchMetadataBatchNumeric(metadata, objectIds) {
|
|
|
750
585
|
}
|
|
751
586
|
// src/utils/matchTokenNumeric.ts
|
|
752
587
|
var RE_NUMERIC = /^[\d.\-]+$/;
|
|
588
|
+
function countDigits(str) {
|
|
589
|
+
let count = 0;
|
|
590
|
+
for (let i = 0;i < str.length; i++) {
|
|
591
|
+
const c = str[i];
|
|
592
|
+
if (c !== "." && c !== "-")
|
|
593
|
+
count++;
|
|
594
|
+
}
|
|
595
|
+
return count;
|
|
596
|
+
}
|
|
597
|
+
function getNumericMatchMode(str, opts) {
|
|
598
|
+
const threshold = opts?.matchNumbersThreshold ?? DEFAULT_SEARCH_OPTS.matchNumbersThreshold;
|
|
599
|
+
const digitCount = countDigits(str);
|
|
600
|
+
if (digitCount <= threshold) {
|
|
601
|
+
return opts?.matchNumbersShort ?? DEFAULT_SEARCH_OPTS.matchNumbersShort;
|
|
602
|
+
}
|
|
603
|
+
return opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers;
|
|
604
|
+
}
|
|
753
605
|
function prepareQueryTokens(queryTokenStrs) {
|
|
754
|
-
return queryTokenStrs.
|
|
606
|
+
return queryTokenStrs.filter((str) => {
|
|
607
|
+
if (str === "-" || str === "--" || str === "~")
|
|
608
|
+
return false;
|
|
609
|
+
return true;
|
|
610
|
+
}).map((str) => {
|
|
755
611
|
let overrideMode;
|
|
756
612
|
let negated = false;
|
|
757
613
|
let cleanStr = str;
|
|
758
614
|
if (str.length > 2 && str.startsWith("--")) {
|
|
759
615
|
negated = true;
|
|
760
616
|
cleanStr = str.slice(2);
|
|
617
|
+
} else if (str.length > 1 && str[0] === "-" && /^[a-z]/i.test(str[1])) {
|
|
618
|
+
negated = true;
|
|
619
|
+
cleanStr = str.slice(1);
|
|
761
620
|
} else if (str.length > 1 && str.startsWith("~")) {
|
|
762
621
|
negated = true;
|
|
763
622
|
cleanStr = str.slice(1);
|
|
@@ -780,13 +639,16 @@ function prepareQueryTokens(queryTokenStrs) {
|
|
|
780
639
|
cleanStr = str.slice(1);
|
|
781
640
|
}
|
|
782
641
|
}
|
|
783
|
-
|
|
642
|
+
const result = {
|
|
784
643
|
str: cleanStr,
|
|
785
644
|
id: findTokenId(cleanStr),
|
|
786
|
-
isNumeric: RE_NUMERIC.test(cleanStr)
|
|
787
|
-
overrideMode,
|
|
788
|
-
negated: negated || undefined
|
|
645
|
+
isNumeric: RE_NUMERIC.test(cleanStr)
|
|
789
646
|
};
|
|
647
|
+
if (overrideMode)
|
|
648
|
+
result.overrideMode = overrideMode;
|
|
649
|
+
if (negated)
|
|
650
|
+
result.negated = true;
|
|
651
|
+
return result;
|
|
790
652
|
});
|
|
791
653
|
}
|
|
792
654
|
function matchWithModeNumeric(searchTokenId, searchTokenStr, targetTokenEncoded, opts, overrideMode) {
|
|
@@ -801,8 +663,8 @@ function matchWithModeNumeric(searchTokenId, searchTokenStr, targetTokenEncoded,
|
|
|
801
663
|
} else if (hasExplicitMode) {
|
|
802
664
|
mode = decodeMatchMode(targetTokenEncoded);
|
|
803
665
|
} else {
|
|
804
|
-
const
|
|
805
|
-
mode =
|
|
666
|
+
const isTargetNumeric = RE_NUMERIC.test(targetTokenStr);
|
|
667
|
+
mode = isTargetNumeric ? getNumericMatchMode(targetTokenStr, opts) : opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
|
|
806
668
|
}
|
|
807
669
|
switch (mode) {
|
|
808
670
|
case "start":
|
|
@@ -837,9 +699,8 @@ function binarySearchUint32(arr, target) {
|
|
|
837
699
|
return false;
|
|
838
700
|
}
|
|
839
701
|
function matchPreparedTokenInSortedList(preparedToken, targetTokens, opts) {
|
|
840
|
-
const { str: searchTokenStr, id: searchTokenId,
|
|
841
|
-
|
|
842
|
-
if (effectiveMode === "whole" && searchTokenId !== -1) {
|
|
702
|
+
const { str: searchTokenStr, id: searchTokenId, overrideMode, negated } = preparedToken;
|
|
703
|
+
if (overrideMode === "whole" && searchTokenId !== -1) {
|
|
843
704
|
let hasEncodedTokens = false;
|
|
844
705
|
for (let i = 0;i < targetTokens.length; i++) {
|
|
845
706
|
if (targetTokens[i] > TOKEN_ID_MASK) {
|
|
@@ -856,47 +717,36 @@ function matchPreparedTokenInSortedList(preparedToken, targetTokens, opts) {
|
|
|
856
717
|
if (matchWithModeNumeric(searchTokenId, searchTokenStr, targetEncoded, opts, overrideMode)) {
|
|
857
718
|
return true;
|
|
858
719
|
}
|
|
720
|
+
if (negated) {
|
|
721
|
+
const targetTokenId = decodeTokenId(targetEncoded);
|
|
722
|
+
const targetTokenStr = tokens[targetTokenId];
|
|
723
|
+
if (targetTokenStr) {
|
|
724
|
+
const hasExplicitMode = targetEncoded !== targetTokenId;
|
|
725
|
+
let targetMode;
|
|
726
|
+
if (overrideMode) {
|
|
727
|
+
targetMode = overrideMode;
|
|
728
|
+
} else if (hasExplicitMode) {
|
|
729
|
+
targetMode = decodeMatchMode(targetEncoded);
|
|
730
|
+
} else {
|
|
731
|
+
const isTargetNumeric = RE_NUMERIC.test(targetTokenStr);
|
|
732
|
+
targetMode = isTargetNumeric ? getNumericMatchMode(targetTokenStr, opts) : opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
|
|
733
|
+
}
|
|
734
|
+
if ((targetMode === "start" || targetMode === "startEnd") && searchTokenStr.startsWith(targetTokenStr)) {
|
|
735
|
+
return true;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
859
739
|
}
|
|
860
740
|
return false;
|
|
861
741
|
}
|
|
862
742
|
function matchTokenInSortedListNumeric(searchTokenStr, targetTokens, opts) {
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
cleanStr = searchTokenStr.slice(2);
|
|
869
|
-
} else if (searchTokenStr.length > 1 && searchTokenStr.startsWith("~")) {
|
|
870
|
-
negated = true;
|
|
871
|
-
cleanStr = searchTokenStr.slice(1);
|
|
872
|
-
} else if (searchTokenStr.length > 3 && searchTokenStr.startsWith("...")) {
|
|
873
|
-
overrideMode = "end";
|
|
874
|
-
cleanStr = searchTokenStr.slice(3);
|
|
875
|
-
} else if (searchTokenStr.length > 2 && searchTokenStr.startsWith("..")) {
|
|
876
|
-
overrideMode = "end";
|
|
877
|
-
cleanStr = searchTokenStr.slice(2);
|
|
878
|
-
} else if (searchTokenStr.length > 3 && searchTokenStr.endsWith("...")) {
|
|
879
|
-
overrideMode = "start";
|
|
880
|
-
cleanStr = searchTokenStr.slice(0, -3);
|
|
881
|
-
} else if (searchTokenStr.length > 2 && searchTokenStr.endsWith("..")) {
|
|
882
|
-
overrideMode = "start";
|
|
883
|
-
cleanStr = searchTokenStr.slice(0, -2);
|
|
884
|
-
} else if (searchTokenStr.length > 1) {
|
|
885
|
-
const firstChar = searchTokenStr[0];
|
|
886
|
-
if (firstChar && PREFIX_TO_MATCH_MODE[firstChar]) {
|
|
887
|
-
overrideMode = PREFIX_TO_MATCH_MODE[firstChar];
|
|
888
|
-
cleanStr = searchTokenStr.slice(1);
|
|
889
|
-
}
|
|
890
|
-
}
|
|
891
|
-
const preparedToken = {
|
|
892
|
-
str: cleanStr,
|
|
893
|
-
id: findTokenId(cleanStr),
|
|
894
|
-
isNumeric: RE_NUMERIC.test(cleanStr),
|
|
895
|
-
overrideMode,
|
|
896
|
-
negated: negated || undefined
|
|
897
|
-
};
|
|
743
|
+
const preparedTokens = prepareQueryTokens([searchTokenStr]);
|
|
744
|
+
if (preparedTokens.length === 0) {
|
|
745
|
+
return true;
|
|
746
|
+
}
|
|
747
|
+
const preparedToken = preparedTokens[0];
|
|
898
748
|
const matches = matchPreparedTokenInSortedList(preparedToken, targetTokens, opts);
|
|
899
|
-
return negated ? !matches : matches;
|
|
749
|
+
return preparedToken.negated ? !matches : matches;
|
|
900
750
|
}
|
|
901
751
|
function allPreparedTokensMatch(preparedTokens, targetTokens, opts) {
|
|
902
752
|
for (const preparedToken of preparedTokens) {
|
|
@@ -918,18 +768,7 @@ function allTokensMatchNumeric(searchTokenStrs, targetTokens, opts) {
|
|
|
918
768
|
|
|
919
769
|
// src/common/numeric/searchInData.ts
|
|
920
770
|
function searchInDataReturnIdsNumeric(query, metadata, opts) {
|
|
921
|
-
|
|
922
|
-
if (queryTokenStrs.length === 0) {
|
|
923
|
-
return [];
|
|
924
|
-
}
|
|
925
|
-
const preparedTokens = prepareQueryTokens(queryTokenStrs);
|
|
926
|
-
const results = [];
|
|
927
|
-
for (const [id, targetTokens] of metadata) {
|
|
928
|
-
if (allPreparedTokensMatch(preparedTokens, targetTokens, opts)) {
|
|
929
|
-
results.push(id);
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
return results;
|
|
771
|
+
return searchInDataReturnIdsWithLimitNumeric(query, metadata, Infinity, opts);
|
|
933
772
|
}
|
|
934
773
|
function searchInDataReturnObjectsNumeric(query, metadata, data, opts) {
|
|
935
774
|
const ids = searchInDataReturnIdsNumeric(query, metadata, opts);
|
|
@@ -963,7 +802,7 @@ function searchInDataReturnIdsWithLimitNumeric(query, metadata, limit, opts) {
|
|
|
963
802
|
function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
964
803
|
const queryTokenStrs = prepareStringForSearch(query);
|
|
965
804
|
if (queryTokenStrs.length === 0) {
|
|
966
|
-
return { queryTokens: queryTokenStrs, results: [] };
|
|
805
|
+
return { queryTokens: queryTokenStrs, results: [], hasNegation: false };
|
|
967
806
|
}
|
|
968
807
|
const preparedTokens = prepareQueryTokens(queryTokenStrs);
|
|
969
808
|
const positiveTokens = preparedTokens.filter((t) => !t.negated);
|
|
@@ -1061,258 +900,184 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
|
1061
900
|
});
|
|
1062
901
|
}
|
|
1063
902
|
}
|
|
1064
|
-
return { queryTokens: queryTokenStrs, results };
|
|
903
|
+
return { queryTokens: queryTokenStrs, results, hasNegation: negatedTokens.length > 0 };
|
|
1065
904
|
}
|
|
1066
905
|
function findInLinkedArraysSimpleNumeric(query, linked, limit = 10, opts) {
|
|
1067
906
|
return findInLinkedArraysNumeric(query, linked, limit, opts).results;
|
|
1068
907
|
}
|
|
1069
|
-
// src/common/
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
908
|
+
// src/common/numeric/AugmentedMetadata.ts
|
|
909
|
+
class AugmentedMetadata {
|
|
910
|
+
baseMetadata;
|
|
911
|
+
augmentedTokens;
|
|
912
|
+
spec;
|
|
913
|
+
constructor(baseMetadata, spec, augmentedDataMap) {
|
|
914
|
+
this.baseMetadata = baseMetadata;
|
|
915
|
+
this.augmentedTokens = new Map;
|
|
916
|
+
this.spec = spec;
|
|
917
|
+
if (augmentedDataMap && augmentedDataMap.size > 0) {
|
|
918
|
+
this.updateAugmentedBatch(augmentedDataMap);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
updateAugmented(id, augmentedData) {
|
|
922
|
+
if (!augmentedData) {
|
|
923
|
+
this.augmentedTokens.delete(id);
|
|
924
|
+
return;
|
|
1078
925
|
}
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
primaryToLinked,
|
|
1084
|
-
primaryData,
|
|
1085
|
-
linkedData
|
|
1086
|
-
};
|
|
1087
|
-
}
|
|
1088
|
-
// src/common/string/updateSearchMetadata.ts
|
|
1089
|
-
function updateSearchMetadata(metadata, objectId, obj, spec) {
|
|
1090
|
-
const tokens2 = obj != null ? prepareObjectForSearch(obj, spec) : undefined;
|
|
1091
|
-
if (tokens2 === undefined) {
|
|
1092
|
-
metadata.delete(objectId);
|
|
1093
|
-
return false;
|
|
1094
|
-
} else {
|
|
1095
|
-
metadata.set(objectId, tokens2);
|
|
1096
|
-
return true;
|
|
1097
|
-
}
|
|
1098
|
-
}
|
|
1099
|
-
function updateSearchMetadataBatch(metadata, batch, spec) {
|
|
1100
|
-
if (batch.length === 0) {
|
|
1101
|
-
return { updated: 0, removed: 0 };
|
|
1102
|
-
}
|
|
1103
|
-
let updated = 0;
|
|
1104
|
-
let removed = 0;
|
|
1105
|
-
for (const { objectId, obj } of batch) {
|
|
1106
|
-
const wasUpdated = updateSearchMetadata(metadata, objectId, obj, spec);
|
|
1107
|
-
if (wasUpdated) {
|
|
1108
|
-
updated++;
|
|
926
|
+
const tokensMap = createTokensMap();
|
|
927
|
+
const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
928
|
+
if (tokens2 && tokens2.length > 0) {
|
|
929
|
+
this.augmentedTokens.set(id, tokens2);
|
|
1109
930
|
} else {
|
|
1110
|
-
|
|
1111
|
-
}
|
|
1112
|
-
}
|
|
1113
|
-
return { updated, removed };
|
|
1114
|
-
}
|
|
1115
|
-
function removeFromSearchMetadata(metadata, objectId) {
|
|
1116
|
-
return metadata.delete(objectId);
|
|
1117
|
-
}
|
|
1118
|
-
function removeFromSearchMetadataBatch(metadata, objectIds) {
|
|
1119
|
-
if (objectIds.length === 0) {
|
|
1120
|
-
return 0;
|
|
1121
|
-
}
|
|
1122
|
-
let removed = 0;
|
|
1123
|
-
for (const id of objectIds) {
|
|
1124
|
-
if (metadata.delete(id)) {
|
|
1125
|
-
removed++;
|
|
931
|
+
this.augmentedTokens.delete(id);
|
|
1126
932
|
}
|
|
933
|
+
clearTokensMap(tokensMap);
|
|
1127
934
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
">": "end",
|
|
1135
|
-
"+": "startEnd",
|
|
1136
|
-
"*": "anywhere",
|
|
1137
|
-
"!": "whole"
|
|
1138
|
-
};
|
|
1139
|
-
function matchWithMode(searchToken, targetToken, mode) {
|
|
1140
|
-
switch (mode) {
|
|
1141
|
-
case "start":
|
|
1142
|
-
return targetToken.startsWith(searchToken);
|
|
1143
|
-
case "end":
|
|
1144
|
-
return targetToken.endsWith(searchToken);
|
|
1145
|
-
case "startEnd":
|
|
1146
|
-
return targetToken.startsWith(searchToken) || targetToken.endsWith(searchToken);
|
|
1147
|
-
case "anywhere":
|
|
1148
|
-
return targetToken.includes(searchToken);
|
|
1149
|
-
case "whole":
|
|
1150
|
-
return targetToken === searchToken;
|
|
1151
|
-
}
|
|
1152
|
-
}
|
|
1153
|
-
function matchToken(searchToken, targetToken, opts) {
|
|
1154
|
-
const firstChar = targetToken[0];
|
|
1155
|
-
const prefixMode = firstChar ? PREFIX_TO_MODE[firstChar] : undefined;
|
|
1156
|
-
if (prefixMode) {
|
|
1157
|
-
const actualTarget = targetToken.slice(1);
|
|
1158
|
-
return matchWithMode(searchToken, actualTarget, prefixMode);
|
|
1159
|
-
}
|
|
1160
|
-
const matchWords = opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
|
|
1161
|
-
const matchNumbers = opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers;
|
|
1162
|
-
const isNumeric = RE_NUMERIC2.test(searchToken);
|
|
1163
|
-
return matchWithMode(searchToken, targetToken, isNumeric ? matchNumbers : matchWords);
|
|
1164
|
-
}
|
|
1165
|
-
function matchTokenInSortedList(searchToken, targetTokens, opts) {
|
|
1166
|
-
const isNumeric = RE_NUMERIC2.test(searchToken);
|
|
1167
|
-
const effectiveMode = isNumeric ? opts?.matchNumbers ?? DEFAULT_SEARCH_OPTS.matchNumbers : opts?.matchWords ?? DEFAULT_SEARCH_OPTS.matchWords;
|
|
1168
|
-
const canEarlyExit = effectiveMode === "start";
|
|
1169
|
-
for (const targetToken of targetTokens) {
|
|
1170
|
-
const firstChar = targetToken[0];
|
|
1171
|
-
const hasPrefix = firstChar ? PREFIX_TO_MODE[firstChar] !== undefined : false;
|
|
1172
|
-
if (hasPrefix) {
|
|
1173
|
-
if (matchToken(searchToken, targetToken, opts)) {
|
|
1174
|
-
return true;
|
|
935
|
+
updateAugmentedBatch(augmentedDataMap) {
|
|
936
|
+
const tokensMap = createTokensMap();
|
|
937
|
+
for (const [id, augmentedData] of augmentedDataMap) {
|
|
938
|
+
if (!augmentedData) {
|
|
939
|
+
this.augmentedTokens.delete(id);
|
|
940
|
+
continue;
|
|
1175
941
|
}
|
|
1176
|
-
|
|
1177
|
-
if (
|
|
1178
|
-
|
|
1179
|
-
return true;
|
|
1180
|
-
}
|
|
1181
|
-
if (targetToken > searchToken && targetToken[0] !== searchToken[0]) {
|
|
1182
|
-
return false;
|
|
1183
|
-
}
|
|
942
|
+
const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
943
|
+
if (tokens2 && tokens2.length > 0) {
|
|
944
|
+
this.augmentedTokens.set(id, tokens2);
|
|
1184
945
|
} else {
|
|
1185
|
-
|
|
1186
|
-
return true;
|
|
1187
|
-
}
|
|
946
|
+
this.augmentedTokens.delete(id);
|
|
1188
947
|
}
|
|
1189
948
|
}
|
|
949
|
+
clearTokensMap(tokensMap);
|
|
1190
950
|
}
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
function allTokensMatch(searchTokens, targetTokens, opts) {
|
|
1194
|
-
for (const searchToken of searchTokens) {
|
|
1195
|
-
if (!matchTokenInSortedList(searchToken, targetTokens, opts)) {
|
|
1196
|
-
return false;
|
|
1197
|
-
}
|
|
951
|
+
clearAugmented(id) {
|
|
952
|
+
this.augmentedTokens.delete(id);
|
|
1198
953
|
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
954
|
+
clearAllAugmented() {
|
|
955
|
+
this.augmentedTokens.clear();
|
|
956
|
+
}
|
|
957
|
+
get(id) {
|
|
958
|
+
const baseTokens = this.baseMetadata.get(id);
|
|
959
|
+
if (!baseTokens)
|
|
960
|
+
return;
|
|
961
|
+
const augTokens = this.augmentedTokens.get(id);
|
|
962
|
+
if (!augTokens)
|
|
963
|
+
return baseTokens;
|
|
964
|
+
return this.mergeSortedTokenArrays(baseTokens, augTokens);
|
|
965
|
+
}
|
|
966
|
+
has(id) {
|
|
967
|
+
return this.baseMetadata.has(id);
|
|
968
|
+
}
|
|
969
|
+
get size() {
|
|
970
|
+
return this.baseMetadata.size;
|
|
971
|
+
}
|
|
972
|
+
[Symbol.iterator]() {
|
|
973
|
+
const self = this;
|
|
974
|
+
const baseIterator = this.baseMetadata[Symbol.iterator]();
|
|
1206
975
|
return {
|
|
1207
|
-
|
|
1208
|
-
|
|
976
|
+
next() {
|
|
977
|
+
const baseResult = baseIterator.next();
|
|
978
|
+
if (baseResult.done) {
|
|
979
|
+
return { done: true, value: undefined };
|
|
980
|
+
}
|
|
981
|
+
const [id, baseTokens] = baseResult.value;
|
|
982
|
+
const augTokens = self.augmentedTokens.get(id);
|
|
983
|
+
const tokens2 = augTokens ? self.mergeSortedTokenArrays(baseTokens, augTokens) : baseTokens;
|
|
984
|
+
return { done: false, value: [id, tokens2] };
|
|
985
|
+
},
|
|
986
|
+
[Symbol.iterator]() {
|
|
987
|
+
return this;
|
|
988
|
+
},
|
|
989
|
+
[Symbol.dispose]() {}
|
|
1209
990
|
};
|
|
1210
991
|
}
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
if (results.length >= limit) {
|
|
1214
|
-
break;
|
|
1215
|
-
}
|
|
1216
|
-
if (allTokensMatch(queryTokens, itemTokens, opts)) {
|
|
1217
|
-
const item = data.get(id);
|
|
1218
|
-
if (item) {
|
|
1219
|
-
results.push({
|
|
1220
|
-
item,
|
|
1221
|
-
tokens: itemTokens
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
992
|
+
keys() {
|
|
993
|
+
return this.baseMetadata.keys();
|
|
1225
994
|
}
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
995
|
+
values() {
|
|
996
|
+
const self = this;
|
|
997
|
+
const keysIterator = this.baseMetadata.keys();
|
|
998
|
+
return {
|
|
999
|
+
next() {
|
|
1000
|
+
const keyResult = keysIterator.next();
|
|
1001
|
+
if (keyResult.done) {
|
|
1002
|
+
return { done: true, value: undefined };
|
|
1003
|
+
}
|
|
1004
|
+
const tokens2 = self.get(keyResult.value);
|
|
1005
|
+
return tokens2 ? { done: false, value: tokens2 } : { done: true, value: undefined };
|
|
1006
|
+
},
|
|
1007
|
+
[Symbol.iterator]() {
|
|
1008
|
+
return this;
|
|
1009
|
+
},
|
|
1010
|
+
[Symbol.dispose]() {}
|
|
1011
|
+
};
|
|
1235
1012
|
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
results.push(id);
|
|
1013
|
+
entries() {
|
|
1014
|
+
return this[Symbol.iterator]();
|
|
1015
|
+
}
|
|
1016
|
+
forEach(callbackfn) {
|
|
1017
|
+
for (const [id, tokens2] of this) {
|
|
1018
|
+
callbackfn(tokens2, id, this);
|
|
1243
1019
|
}
|
|
1244
1020
|
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
// src/common/findInArray.ts
|
|
1249
|
-
function findInArray(query, data, metadata, limit = 10, opts) {
|
|
1250
|
-
const result = findInArrayReturnDataAndMeta(query, data, metadata, limit, opts);
|
|
1251
|
-
return result.results.map((r) => r.item);
|
|
1252
|
-
}
|
|
1253
|
-
// src/common/findInLinkedArrays.ts
|
|
1254
|
-
function findInLinkedArrays(query, linked, limit = 10, opts) {
|
|
1255
|
-
const queryTokens = prepareStringForSearch(query);
|
|
1256
|
-
if (queryTokens.length === 0) {
|
|
1257
|
-
return { queryTokens, results: [] };
|
|
1021
|
+
set(_key, _value) {
|
|
1022
|
+
throw new Error("AugmentedMetadata.set() is not supported. Use updateAugmented() instead.");
|
|
1258
1023
|
}
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
const tokensMatchingPrimary = new Set;
|
|
1280
|
-
for (const queryToken of queryTokens) {
|
|
1281
|
-
if (matchTokenInSortedList(queryToken, primaryTokens, opts)) {
|
|
1282
|
-
anyMatchInPrimary = true;
|
|
1283
|
-
tokensMatchingPrimary.add(queryToken);
|
|
1024
|
+
delete(_key) {
|
|
1025
|
+
throw new Error("AugmentedMetadata.delete() is not supported. Use clearAugmented() instead.");
|
|
1026
|
+
}
|
|
1027
|
+
clear() {
|
|
1028
|
+
throw new Error("AugmentedMetadata.clear() is not supported. Use clearAllAugmented() instead.");
|
|
1029
|
+
}
|
|
1030
|
+
get [Symbol.toStringTag]() {
|
|
1031
|
+
return "AugmentedMetadata";
|
|
1032
|
+
}
|
|
1033
|
+
mergeSortedTokenArrays(a, b) {
|
|
1034
|
+
const merged = new Uint32Array(a.length + b.length);
|
|
1035
|
+
let i = 0, j = 0, k = 0;
|
|
1036
|
+
let lastToken = -1;
|
|
1037
|
+
while (i < a.length && j < b.length) {
|
|
1038
|
+
const tokenA = a[i];
|
|
1039
|
+
const tokenB = b[j];
|
|
1040
|
+
if (tokenA < tokenB) {
|
|
1041
|
+
if (tokenA !== lastToken) {
|
|
1042
|
+
merged[k++] = tokenA;
|
|
1043
|
+
lastToken = tokenA;
|
|
1284
1044
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
}
|
|
1045
|
+
i++;
|
|
1046
|
+
} else if (tokenA > tokenB) {
|
|
1047
|
+
if (tokenB !== lastToken) {
|
|
1048
|
+
merged[k++] = tokenB;
|
|
1049
|
+
lastToken = tokenB;
|
|
1050
|
+
}
|
|
1051
|
+
j++;
|
|
1052
|
+
} else {
|
|
1053
|
+
if (tokenA !== lastToken) {
|
|
1054
|
+
merged[k++] = tokenA;
|
|
1055
|
+
lastToken = tokenA;
|
|
1297
1056
|
}
|
|
1057
|
+
i++;
|
|
1058
|
+
j++;
|
|
1298
1059
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
1060
|
+
}
|
|
1061
|
+
while (i < a.length) {
|
|
1062
|
+
const tokenA = a[i];
|
|
1063
|
+
if (tokenA !== lastToken) {
|
|
1064
|
+
merged[k++] = tokenA;
|
|
1065
|
+
lastToken = tokenA;
|
|
1301
1066
|
}
|
|
1302
|
-
|
|
1303
|
-
results.push({
|
|
1304
|
-
primary,
|
|
1305
|
-
linked: matchedLinked,
|
|
1306
|
-
matchedIn: anyMatchInPrimary && anyMatchInLinked ? "both" : anyMatchInPrimary ? "primary" : "linked"
|
|
1307
|
-
});
|
|
1067
|
+
i++;
|
|
1308
1068
|
}
|
|
1069
|
+
while (j < b.length) {
|
|
1070
|
+
const tokenB = b[j];
|
|
1071
|
+
if (tokenB !== lastToken) {
|
|
1072
|
+
merged[k++] = tokenB;
|
|
1073
|
+
lastToken = tokenB;
|
|
1074
|
+
}
|
|
1075
|
+
j++;
|
|
1076
|
+
}
|
|
1077
|
+
return merged.slice(0, k);
|
|
1309
1078
|
}
|
|
1310
|
-
return { queryTokens, results };
|
|
1311
|
-
}
|
|
1312
|
-
function findInLinkedArraysSimple(query, linked, limit = 10, opts) {
|
|
1313
|
-
return findInLinkedArrays(query, linked, limit, opts).results;
|
|
1314
1079
|
}
|
|
1315
|
-
// src/common/syncSearchArrayMetadata.ts
|
|
1080
|
+
// src/common/numeric/syncSearchArrayMetadata.ts
|
|
1316
1081
|
function tokensEqual(a, b) {
|
|
1317
1082
|
if (a.length !== b.length)
|
|
1318
1083
|
return false;
|
|
@@ -1322,7 +1087,7 @@ function tokensEqual(a, b) {
|
|
|
1322
1087
|
}
|
|
1323
1088
|
return true;
|
|
1324
1089
|
}
|
|
1325
|
-
function
|
|
1090
|
+
function syncSearchArrayMetadataNumeric(metadata, newData, spec) {
|
|
1326
1091
|
const result = {
|
|
1327
1092
|
added: 0,
|
|
1328
1093
|
updated: 0,
|
|
@@ -1331,6 +1096,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
|
|
|
1331
1096
|
updatedIds: [],
|
|
1332
1097
|
removedIds: []
|
|
1333
1098
|
};
|
|
1099
|
+
const tokensMap = createTokensMap();
|
|
1334
1100
|
for (const id of metadata.keys()) {
|
|
1335
1101
|
if (!newData.has(id)) {
|
|
1336
1102
|
metadata.delete(id);
|
|
@@ -1339,7 +1105,7 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
|
|
|
1339
1105
|
}
|
|
1340
1106
|
}
|
|
1341
1107
|
for (const [id, item] of newData) {
|
|
1342
|
-
const newTokens =
|
|
1108
|
+
const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1343
1109
|
if (newTokens === undefined) {
|
|
1344
1110
|
if (metadata.has(id)) {
|
|
1345
1111
|
metadata.delete(id);
|
|
@@ -1359,9 +1125,10 @@ function syncSearchArrayMetadata(metadata, newData, spec) {
|
|
|
1359
1125
|
result.updatedIds.push(id);
|
|
1360
1126
|
}
|
|
1361
1127
|
}
|
|
1128
|
+
clearTokensMap(tokensMap);
|
|
1362
1129
|
return result;
|
|
1363
1130
|
}
|
|
1364
|
-
function
|
|
1131
|
+
function syncSearchArrayMetadataNumericWithPrevious(metadata, previousData, newData, options, spec) {
|
|
1365
1132
|
const result = {
|
|
1366
1133
|
added: 0,
|
|
1367
1134
|
updated: 0,
|
|
@@ -1370,6 +1137,7 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
|
|
|
1370
1137
|
updatedIds: [],
|
|
1371
1138
|
removedIds: []
|
|
1372
1139
|
};
|
|
1140
|
+
const tokensMap = createTokensMap();
|
|
1373
1141
|
for (const id of previousData.keys()) {
|
|
1374
1142
|
if (!newData.has(id)) {
|
|
1375
1143
|
metadata.delete(id);
|
|
@@ -1380,14 +1148,14 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
|
|
|
1380
1148
|
for (const [id, item] of newData) {
|
|
1381
1149
|
const wasInPrevious = previousData.has(id);
|
|
1382
1150
|
if (!wasInPrevious) {
|
|
1383
|
-
const tokens2 =
|
|
1151
|
+
const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1384
1152
|
if (tokens2 !== undefined) {
|
|
1385
1153
|
metadata.set(id, tokens2);
|
|
1386
1154
|
result.added++;
|
|
1387
1155
|
result.addedIds.push(id);
|
|
1388
1156
|
}
|
|
1389
1157
|
} else if (!options?.skipUpdateCheck) {
|
|
1390
|
-
const newTokens =
|
|
1158
|
+
const newTokens = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1391
1159
|
if (newTokens === undefined) {
|
|
1392
1160
|
metadata.delete(id);
|
|
1393
1161
|
result.removed++;
|
|
@@ -1402,9 +1170,10 @@ function syncSearchArrayMetadataWithPrevious(metadata, previousData, newData, op
|
|
|
1402
1170
|
}
|
|
1403
1171
|
}
|
|
1404
1172
|
}
|
|
1173
|
+
clearTokensMap(tokensMap);
|
|
1405
1174
|
return result;
|
|
1406
1175
|
}
|
|
1407
|
-
// src/common/updateSearchLinkedMetadata.ts
|
|
1176
|
+
// src/common/numeric/updateSearchLinkedMetadata.ts
|
|
1408
1177
|
function tokensEqual2(a, b) {
|
|
1409
1178
|
if (a.length !== b.length)
|
|
1410
1179
|
return false;
|
|
@@ -1414,11 +1183,13 @@ function tokensEqual2(a, b) {
|
|
|
1414
1183
|
}
|
|
1415
1184
|
return true;
|
|
1416
1185
|
}
|
|
1417
|
-
function
|
|
1186
|
+
function upsertPrimaryItemNumeric(linked, item, spec) {
|
|
1418
1187
|
const id = item._id;
|
|
1419
1188
|
const wasAdded = !linked.primaryData.has(id);
|
|
1420
1189
|
linked.primaryData.set(id, item);
|
|
1421
|
-
const
|
|
1190
|
+
const tokensMap = createTokensMap();
|
|
1191
|
+
const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1192
|
+
clearTokensMap(tokensMap);
|
|
1422
1193
|
if (tokens2 !== undefined) {
|
|
1423
1194
|
linked.primaryMeta.set(id, tokens2);
|
|
1424
1195
|
} else {
|
|
@@ -1429,7 +1200,7 @@ function upsertPrimaryItem(linked, item, spec) {
|
|
|
1429
1200
|
}
|
|
1430
1201
|
return { added: wasAdded };
|
|
1431
1202
|
}
|
|
1432
|
-
function
|
|
1203
|
+
function removePrimaryItemNumeric(linked, primaryId) {
|
|
1433
1204
|
if (!linked.primaryData.has(primaryId)) {
|
|
1434
1205
|
return false;
|
|
1435
1206
|
}
|
|
@@ -1438,7 +1209,7 @@ function removePrimaryItem(linked, primaryId) {
|
|
|
1438
1209
|
linked.primaryToLinked.delete(primaryId);
|
|
1439
1210
|
return true;
|
|
1440
1211
|
}
|
|
1441
|
-
function
|
|
1212
|
+
function upsertLinkedItemNumeric(linked, item, foreignKeyGetter, spec) {
|
|
1442
1213
|
const id = item._id;
|
|
1443
1214
|
const newPrimaryId = foreignKeyGetter(item);
|
|
1444
1215
|
let previousPrimaryId;
|
|
@@ -1448,7 +1219,9 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
|
|
|
1448
1219
|
}
|
|
1449
1220
|
const wasAdded = !existingItem;
|
|
1450
1221
|
linked.linkedData.set(id, item);
|
|
1451
|
-
const
|
|
1222
|
+
const tokensMap = createTokensMap();
|
|
1223
|
+
const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1224
|
+
clearTokensMap(tokensMap);
|
|
1452
1225
|
if (tokens2 !== undefined) {
|
|
1453
1226
|
linked.linkedMeta.set(id, tokens2);
|
|
1454
1227
|
} else {
|
|
@@ -1480,7 +1253,7 @@ function upsertLinkedItem(linked, item, foreignKeyGetter, spec) {
|
|
|
1480
1253
|
previousPrimaryId: wasAdded ? undefined : previousPrimaryId
|
|
1481
1254
|
};
|
|
1482
1255
|
}
|
|
1483
|
-
function
|
|
1256
|
+
function removeLinkedItemNumeric(linked, linkedId, foreignKeyGetter) {
|
|
1484
1257
|
const existingItem = linked.linkedData.get(linkedId);
|
|
1485
1258
|
if (!existingItem) {
|
|
1486
1259
|
return false;
|
|
@@ -1499,12 +1272,13 @@ function removeLinkedItem(linked, linkedId, foreignKeyGetter) {
|
|
|
1499
1272
|
}
|
|
1500
1273
|
return true;
|
|
1501
1274
|
}
|
|
1502
|
-
function
|
|
1275
|
+
function syncLinkedItemsForPrimaryNumeric(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
|
|
1503
1276
|
const result = {
|
|
1504
1277
|
added: 0,
|
|
1505
1278
|
updated: 0,
|
|
1506
1279
|
removed: 0
|
|
1507
1280
|
};
|
|
1281
|
+
const tokensMap = createTokensMap();
|
|
1508
1282
|
const currentLinkedIds = new Set(linked.primaryToLinked.get(primaryId) || []);
|
|
1509
1283
|
const newLinkedIds = new Set;
|
|
1510
1284
|
for (const [id, item] of newLinkedItems) {
|
|
@@ -1524,7 +1298,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
|
|
|
1524
1298
|
}
|
|
1525
1299
|
for (const id of newLinkedIds) {
|
|
1526
1300
|
const item = newLinkedItems.get(id);
|
|
1527
|
-
const tokens2 =
|
|
1301
|
+
const tokens2 = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1528
1302
|
if (currentLinkedIds.has(id)) {
|
|
1529
1303
|
const existingTokens = linked.linkedMeta.get(id);
|
|
1530
1304
|
if (tokens2 !== undefined) {
|
|
@@ -1543,6 +1317,7 @@ function syncLinkedItemsForPrimary(linked, primaryId, newLinkedItems, foreignKey
|
|
|
1543
1317
|
}
|
|
1544
1318
|
}
|
|
1545
1319
|
linked.primaryToLinked.set(primaryId, Array.from(newLinkedIds));
|
|
1320
|
+
clearTokensMap(tokensMap);
|
|
1546
1321
|
return result;
|
|
1547
1322
|
}
|
|
1548
1323
|
// src/common/SearchUniverse.ts
|
|
@@ -1779,7 +1554,7 @@ class SearchUniverse {
|
|
|
1779
1554
|
const linkedSearchResults = findInLinkedArraysNumeric(query, linkedMetadata, limit, searchOpts);
|
|
1780
1555
|
if (linkedSearchResults.results.length > 0) {
|
|
1781
1556
|
const combinedResults = [];
|
|
1782
|
-
const hasNegation =
|
|
1557
|
+
const hasNegation = linkedSearchResults.hasNegation;
|
|
1783
1558
|
for (const result of linkedSearchResults.results) {
|
|
1784
1559
|
let linkedItems = result.linked;
|
|
1785
1560
|
if (result.matchedIn === "primary" && !hasNegation) {
|