cry-search 1.0.6 → 1.0.8
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 +79 -78
- package/README.md +93 -17
- package/UNIVERSE.md +29 -20
- package/dist/common/SearchUniverse.d.ts +28 -13
- package/dist/common/SearchUniverse.d.ts.map +1 -1
- package/dist/common/numeric/AugmentedMetadata.d.ts +27 -92
- package/dist/common/numeric/AugmentedMetadata.d.ts.map +1 -1
- package/dist/common/numeric/createSearchArrayMetadata.d.ts +47 -7
- package/dist/common/numeric/createSearchArrayMetadata.d.ts.map +1 -1
- package/dist/common/numeric/findInLinkedArrays.d.ts +7 -4
- package/dist/common/numeric/findInLinkedArrays.d.ts.map +1 -1
- package/dist/common/numeric/scoring.d.ts +95 -0
- package/dist/common/numeric/scoring.d.ts.map +1 -0
- package/dist/common/numeric/searchAndRank.d.ts +48 -0
- package/dist/common/numeric/searchAndRank.d.ts.map +1 -0
- package/dist/common/numeric/searchInData.d.ts +17 -9
- package/dist/common/numeric/searchInData.d.ts.map +1 -1
- package/dist/common/numeric/syncSearchArrayMetadata.d.ts +7 -50
- package/dist/common/numeric/syncSearchArrayMetadata.d.ts.map +1 -1
- package/dist/common/numeric/updateSearchLinkedMetadata.d.ts +11 -110
- package/dist/common/numeric/updateSearchLinkedMetadata.d.ts.map +1 -1
- package/dist/common/numeric/updateSearchMetadata.d.ts.map +1 -1
- package/dist/index.cjs +646 -312
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +646 -312
- package/dist/types/index.d.ts +35 -50
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/matchTokenNumeric.d.ts.map +1 -1
- package/dist/utils/prepareStringForSearchNumeric.d.ts +24 -29
- package/dist/utils/prepareStringForSearchNumeric.d.ts.map +1 -1
- package/package.json +4 -14
- package/dist/common/findInArray.d.ts +0 -37
- package/dist/common/findInArray.d.ts.map +0 -1
- package/dist/common/findInArrayReturnDataAndMeta.d.ts +0 -52
- package/dist/common/findInArrayReturnDataAndMeta.d.ts.map +0 -1
- package/dist/common/findInLinkedArrays.d.ts +0 -66
- package/dist/common/findInLinkedArrays.d.ts.map +0 -1
- package/dist/common/string/createSearchArrayMetadata.d.ts +0 -117
- package/dist/common/string/createSearchArrayMetadata.d.ts.map +0 -1
- package/dist/common/string/createSearchLinkedMetadata.d.ts +0 -36
- package/dist/common/string/createSearchLinkedMetadata.d.ts.map +0 -1
- package/dist/common/string/index.d.ts +0 -10
- package/dist/common/string/index.d.ts.map +0 -1
- package/dist/common/string/updateSearchMetadata.d.ts +0 -103
- package/dist/common/string/updateSearchMetadata.d.ts.map +0 -1
- package/dist/common/syncSearchArrayMetadata.d.ts +0 -68
- package/dist/common/syncSearchArrayMetadata.d.ts.map +0 -1
- package/dist/common/updateSearchLinkedMetadata.d.ts +0 -139
- package/dist/common/updateSearchLinkedMetadata.d.ts.map +0 -1
- package/dist/string.cjs +0 -930
- package/dist/string.d.cts +0 -26
- package/dist/string.d.ts +0 -26
- package/dist/string.d.ts.map +0 -1
- package/dist/string.js +0 -898
- package/dist/utils/matchToken.d.ts +0 -65
- package/dist/utils/matchToken.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,11 @@ __export(exports_src, {
|
|
|
43
43
|
searchInDataReturnObjects: () => searchInDataReturnObjectsNumeric,
|
|
44
44
|
searchInDataReturnIds: () => searchInDataReturnIdsNumeric,
|
|
45
45
|
searchInData: () => searchInDataReturnIdsNumeric,
|
|
46
|
+
searchAndRankNumeric: () => searchAndRankNumeric,
|
|
47
|
+
searchAndRank: () => searchAndRankNumeric,
|
|
48
|
+
scoreOrderAndPresence: () => scoreOrderAndPresence,
|
|
49
|
+
scoreOne: () => scoreOne,
|
|
50
|
+
scoreBag: () => scoreBag,
|
|
46
51
|
sanitiseString: () => sanitiseString,
|
|
47
52
|
resetTokenRegistry: () => resetTokenRegistry,
|
|
48
53
|
removePrimaryItem: () => removePrimaryItemNumeric,
|
|
@@ -54,6 +59,7 @@ __export(exports_src, {
|
|
|
54
59
|
prepareStringForSearch: () => prepareStringForSearch,
|
|
55
60
|
prepareQueryTokens: () => prepareQueryTokens,
|
|
56
61
|
prepareObjectForSearch: () => prepareObjectForSearchNumeric,
|
|
62
|
+
orderedTokenize: () => orderedTokenize,
|
|
57
63
|
normalizeDates: () => normalizeDates,
|
|
58
64
|
matchTokenInSortedListNumeric: () => matchTokenInSortedListNumeric,
|
|
59
65
|
matchPreparedTokenInSortedList: () => matchPreparedTokenInSortedList,
|
|
@@ -77,6 +83,8 @@ __export(exports_src, {
|
|
|
77
83
|
allPreparedTokensMatch: () => allPreparedTokensMatch,
|
|
78
84
|
TOKEN_ID_MASK: () => TOKEN_ID_MASK,
|
|
79
85
|
SearchUniverse: () => SearchUniverse,
|
|
86
|
+
PREFIX_TO_MATCH_MODE: () => PREFIX_TO_MATCH_MODE,
|
|
87
|
+
MATCH_MODE_PREFIXES: () => MATCH_MODE_PREFIXES,
|
|
80
88
|
MATCH_MODE_BITS: () => MATCH_MODE_BITS,
|
|
81
89
|
DEFAULT_SEARCH_OPTS: () => DEFAULT_SEARCH_OPTS,
|
|
82
90
|
AugmentedMetadata: () => AugmentedMetadata
|
|
@@ -84,6 +92,7 @@ __export(exports_src, {
|
|
|
84
92
|
module.exports = __toCommonJS(exports_src);
|
|
85
93
|
|
|
86
94
|
// src/types/index.ts
|
|
95
|
+
var DEFAULT_FIRST_TOKENS_N = 8;
|
|
87
96
|
var DEFAULT_SEARCH_OPTS = {
|
|
88
97
|
matchWords: "start",
|
|
89
98
|
matchNumbers: "startEnd",
|
|
@@ -353,11 +362,23 @@ function prepareStringForSearchNumeric(input, tokensMap) {
|
|
|
353
362
|
for (let i = 0;i < stringTokens.length; i++) {
|
|
354
363
|
numericTokens[i] = getOrCreateTokenId(stringTokens[i], tokensMap);
|
|
355
364
|
}
|
|
356
|
-
|
|
357
|
-
|
|
365
|
+
const unsorted = Uint32Array.from(numericTokens);
|
|
366
|
+
const sortedArr = numericTokens.slice().sort((a, b) => a - b);
|
|
367
|
+
const sorted = Uint32Array.from(sortedArr);
|
|
368
|
+
return { sorted, unsorted };
|
|
358
369
|
}
|
|
359
370
|
|
|
360
|
-
// src/common/
|
|
371
|
+
// src/common/numeric/createSearchArrayMetadata.ts
|
|
372
|
+
function isDeletedOrBlocked(obj) {
|
|
373
|
+
return obj._deleted != null || obj._blocked != null;
|
|
374
|
+
}
|
|
375
|
+
var MATCH_MODE_PREFIXES = {
|
|
376
|
+
start: "<",
|
|
377
|
+
end: ">",
|
|
378
|
+
startEnd: "+",
|
|
379
|
+
anywhere: "*",
|
|
380
|
+
whole: "!"
|
|
381
|
+
};
|
|
361
382
|
var PREFIX_TO_MATCH_MODE = {
|
|
362
383
|
"<": "start",
|
|
363
384
|
">": "end",
|
|
@@ -367,12 +388,6 @@ var PREFIX_TO_MATCH_MODE = {
|
|
|
367
388
|
"=": "whole",
|
|
368
389
|
"?": "anywhere"
|
|
369
390
|
};
|
|
370
|
-
var DEFAULT_EXCLUDED_FIELDS = new Set(["_id", "_deleted", "_blocked"]);
|
|
371
|
-
function isDeletedOrBlocked(obj) {
|
|
372
|
-
return obj._deleted != null || obj._blocked != null;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// src/common/numeric/createSearchArrayMetadata.ts
|
|
376
391
|
var MATCH_MODE_BITS = {
|
|
377
392
|
start: 0,
|
|
378
393
|
end: 1,
|
|
@@ -403,7 +418,7 @@ function decodeMatchMode(encoded) {
|
|
|
403
418
|
return "start";
|
|
404
419
|
}
|
|
405
420
|
}
|
|
406
|
-
var
|
|
421
|
+
var DEFAULT_EXCLUDED_FIELDS = new Set(["_id", "_deleted", "_blocked"]);
|
|
407
422
|
function getValueByPath(obj, path) {
|
|
408
423
|
const parts = path.split(".");
|
|
409
424
|
let current = obj;
|
|
@@ -460,26 +475,29 @@ function prepareObjectForSearchNumeric(obj, spec, tokensMap) {
|
|
|
460
475
|
if (isDeletedOrBlocked(obj)) {
|
|
461
476
|
return;
|
|
462
477
|
}
|
|
463
|
-
if (spec?.extractSearchableStringFn) {
|
|
464
|
-
const searchableString = spec.extractSearchableStringFn(obj);
|
|
465
|
-
if (searchableString === undefined) {
|
|
466
|
-
return;
|
|
467
|
-
}
|
|
468
|
-
return prepareStringForSearchNumeric(searchableString, tokensMap);
|
|
469
|
-
}
|
|
470
|
-
return prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap);
|
|
471
|
-
}
|
|
472
|
-
function prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap) {
|
|
473
478
|
if (spec?.enrichSearchObjectFn) {
|
|
474
479
|
spec.enrichSearchObjectFn(obj, spec.searchContext);
|
|
475
480
|
}
|
|
481
|
+
const sorted = spec?.extractSearchableStringFn ? buildSortedFromExtractFn(obj, spec.extractSearchableStringFn, tokensMap) : buildSortedFromFields(obj, spec, tokensMap);
|
|
482
|
+
if (sorted === undefined)
|
|
483
|
+
return;
|
|
484
|
+
const firstN = spec?.keyFields && spec.keyFields.length > 0 ? buildFirstNFromKeyFields(obj, spec.keyFields, spec.firstTokensN ?? DEFAULT_FIRST_TOKENS_N, tokensMap) : undefined;
|
|
485
|
+
return { sorted, firstN };
|
|
486
|
+
}
|
|
487
|
+
function buildSortedFromExtractFn(obj, extractFn, tokensMap) {
|
|
488
|
+
const str = extractFn(obj);
|
|
489
|
+
if (str === undefined)
|
|
490
|
+
return;
|
|
491
|
+
return prepareStringForSearchNumeric(str, tokensMap).sorted;
|
|
492
|
+
}
|
|
493
|
+
function buildSortedFromFields(obj, spec, tokensMap) {
|
|
476
494
|
const allTokens = [];
|
|
477
495
|
const fieldMatchModes = spec?.fieldMatchModes;
|
|
478
496
|
const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
|
|
479
497
|
const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
|
|
480
498
|
for (const key of fieldsToSearch) {
|
|
481
499
|
const keyStr = key;
|
|
482
|
-
if (!spec?.searchInFields &&
|
|
500
|
+
if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
|
|
483
501
|
continue;
|
|
484
502
|
if (fieldsToExclude.has(key))
|
|
485
503
|
continue;
|
|
@@ -510,14 +528,42 @@ function prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap) {
|
|
|
510
528
|
const uniqueTokens = [...new Set(allTokens)].sort((a, b) => a - b);
|
|
511
529
|
return new Uint32Array(uniqueTokens);
|
|
512
530
|
}
|
|
531
|
+
function buildFirstNFromKeyFields(obj, keyFields, n, tokensMap) {
|
|
532
|
+
const strings = [];
|
|
533
|
+
for (const field of keyFields) {
|
|
534
|
+
const keyStr = field;
|
|
535
|
+
const value = isDotNotation(keyStr) ? getValueByPath(obj, keyStr) : obj[field];
|
|
536
|
+
if (value == null)
|
|
537
|
+
continue;
|
|
538
|
+
extractStringsFromValue(value, strings);
|
|
539
|
+
}
|
|
540
|
+
if (strings.length === 0)
|
|
541
|
+
return;
|
|
542
|
+
const text = strings.join(" ");
|
|
543
|
+
const datesNormalized = normalizeDates(text);
|
|
544
|
+
const preprocessed = preprocessString(datesNormalized);
|
|
545
|
+
const sanitised = sanitiseString(preprocessed);
|
|
546
|
+
const stringTokens = tokenize(sanitised, DEFAULT_TOKENIZE_CONFIG);
|
|
547
|
+
if (stringTokens.length === 0)
|
|
548
|
+
return;
|
|
549
|
+
const sliced = stringTokens.slice(0, n);
|
|
550
|
+
const out = new Uint32Array(sliced.length);
|
|
551
|
+
for (let i = 0;i < sliced.length; i++) {
|
|
552
|
+
out[i] = getOrCreateTokenId(sliced[i], tokensMap);
|
|
553
|
+
}
|
|
554
|
+
return out;
|
|
555
|
+
}
|
|
513
556
|
function createSearchArrayMetadataNumeric(data, spec) {
|
|
514
557
|
const tokensMap = createTokensMap();
|
|
515
558
|
try {
|
|
516
|
-
const metadata =
|
|
559
|
+
const metadata = emptyNumericSearchMetadata();
|
|
517
560
|
for (const [id, item] of data) {
|
|
518
|
-
const
|
|
519
|
-
if (
|
|
520
|
-
metadata.set(id,
|
|
561
|
+
const result = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
562
|
+
if (result !== undefined) {
|
|
563
|
+
metadata.sorted.set(id, result.sorted);
|
|
564
|
+
if (result.firstN !== undefined) {
|
|
565
|
+
metadata.unsorted.set(id, result.firstN);
|
|
566
|
+
}
|
|
521
567
|
}
|
|
522
568
|
}
|
|
523
569
|
return metadata;
|
|
@@ -525,6 +571,9 @@ function createSearchArrayMetadataNumeric(data, spec) {
|
|
|
525
571
|
clearTokensMap(tokensMap);
|
|
526
572
|
}
|
|
527
573
|
}
|
|
574
|
+
function emptyNumericSearchMetadata() {
|
|
575
|
+
return { sorted: new Map, unsorted: new Map };
|
|
576
|
+
}
|
|
528
577
|
// src/common/numeric/createSearchLinkedMetadata.ts
|
|
529
578
|
function createSearchLinkedMetadataNumeric(primaryData, primaryMetadata, linkedData, linkedMetadata, foreignKeyGetter) {
|
|
530
579
|
const primaryToLinked = new Map;
|
|
@@ -546,14 +595,19 @@ function createSearchLinkedMetadataNumeric(primaryData, primaryMetadata, linkedD
|
|
|
546
595
|
}
|
|
547
596
|
// src/common/numeric/updateSearchMetadata.ts
|
|
548
597
|
function updateSearchMetadataNumeric(metadata, objectId, obj, spec, tokensMap) {
|
|
549
|
-
const
|
|
550
|
-
if (
|
|
551
|
-
metadata.delete(objectId);
|
|
598
|
+
const result = obj != null ? prepareObjectForSearchNumeric(obj, spec, tokensMap) : undefined;
|
|
599
|
+
if (result === undefined) {
|
|
600
|
+
metadata.sorted.delete(objectId);
|
|
601
|
+
metadata.unsorted.delete(objectId);
|
|
552
602
|
return false;
|
|
603
|
+
}
|
|
604
|
+
metadata.sorted.set(objectId, result.sorted);
|
|
605
|
+
if (result.firstN !== undefined) {
|
|
606
|
+
metadata.unsorted.set(objectId, result.firstN);
|
|
553
607
|
} else {
|
|
554
|
-
metadata.
|
|
555
|
-
return true;
|
|
608
|
+
metadata.unsorted.delete(objectId);
|
|
556
609
|
}
|
|
610
|
+
return true;
|
|
557
611
|
}
|
|
558
612
|
function updateSearchMetadataBatchNumeric(metadata, batch, spec) {
|
|
559
613
|
if (batch.length === 0) {
|
|
@@ -577,7 +631,9 @@ function updateSearchMetadataBatchNumeric(metadata, batch, spec) {
|
|
|
577
631
|
}
|
|
578
632
|
}
|
|
579
633
|
function removeFromSearchMetadataNumeric(metadata, objectId) {
|
|
580
|
-
|
|
634
|
+
const had = metadata.sorted.delete(objectId);
|
|
635
|
+
metadata.unsorted.delete(objectId);
|
|
636
|
+
return had;
|
|
581
637
|
}
|
|
582
638
|
function removeFromSearchMetadataBatchNumeric(metadata, objectIds) {
|
|
583
639
|
if (objectIds.length === 0) {
|
|
@@ -585,9 +641,10 @@ function removeFromSearchMetadataBatchNumeric(metadata, objectIds) {
|
|
|
585
641
|
}
|
|
586
642
|
let removed = 0;
|
|
587
643
|
for (const id of objectIds) {
|
|
588
|
-
|
|
644
|
+
const had = metadata.sorted.delete(id);
|
|
645
|
+
metadata.unsorted.delete(id);
|
|
646
|
+
if (had)
|
|
589
647
|
removed++;
|
|
590
|
-
}
|
|
591
648
|
}
|
|
592
649
|
return removed;
|
|
593
650
|
}
|
|
@@ -777,6 +834,106 @@ function allTokensMatchNumeric(searchTokenStrs, targetTokens, opts) {
|
|
|
777
834
|
return allPreparedTokensMatch(preparedTokens, targetTokens, opts);
|
|
778
835
|
}
|
|
779
836
|
|
|
837
|
+
// src/common/numeric/scoring.ts
|
|
838
|
+
function orderedTokenize(input) {
|
|
839
|
+
return tokenize(sanitiseString(preprocessString(normalizeDates(input))), DEFAULT_TOKENIZE_CONFIG);
|
|
840
|
+
}
|
|
841
|
+
function scoreOne(query, qTokens, itemTokens, exactKeys) {
|
|
842
|
+
if (exactKeys && exactKeys.length > 0) {
|
|
843
|
+
for (let i = 0;i < exactKeys.length; i++) {
|
|
844
|
+
if (exactKeys[i] === query)
|
|
845
|
+
return 1e5;
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
if (qTokens.length === 0)
|
|
849
|
+
return 0;
|
|
850
|
+
if (itemTokens.length === 0)
|
|
851
|
+
return 1;
|
|
852
|
+
let qi = 0;
|
|
853
|
+
const positions = [];
|
|
854
|
+
for (let i = 0;i < itemTokens.length; i++) {
|
|
855
|
+
if (qi < qTokens.length && itemTokens[i].startsWith(qTokens[qi])) {
|
|
856
|
+
positions.push(i);
|
|
857
|
+
qi++;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
if (qi === 0)
|
|
861
|
+
return 1;
|
|
862
|
+
let score = 50;
|
|
863
|
+
if (qi === qTokens.length)
|
|
864
|
+
score += 100;
|
|
865
|
+
if (positions[0] === 0)
|
|
866
|
+
score += 50;
|
|
867
|
+
let perfect = qi === qTokens.length;
|
|
868
|
+
if (perfect) {
|
|
869
|
+
for (let i = 0;i < positions.length; i++) {
|
|
870
|
+
if (positions[i] !== i) {
|
|
871
|
+
perfect = false;
|
|
872
|
+
break;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
if (perfect)
|
|
877
|
+
score += 80;
|
|
878
|
+
if (positions.length >= 2) {
|
|
879
|
+
const span = positions[positions.length - 1] - positions[0] + 1;
|
|
880
|
+
score += positions.length / span * 30;
|
|
881
|
+
}
|
|
882
|
+
let totalLen = 0;
|
|
883
|
+
for (const t of itemTokens)
|
|
884
|
+
totalLen += t.length + 1;
|
|
885
|
+
score -= totalLen * 0.1;
|
|
886
|
+
return score;
|
|
887
|
+
}
|
|
888
|
+
function scoreBag(qTokens, itemTokens, perTokenWeight = 30) {
|
|
889
|
+
if (qTokens.length === 0 || itemTokens.length === 0)
|
|
890
|
+
return 0;
|
|
891
|
+
const usedItemIdx = new Set;
|
|
892
|
+
let score = 0;
|
|
893
|
+
for (const qt of qTokens) {
|
|
894
|
+
for (let i = 0;i < itemTokens.length; i++) {
|
|
895
|
+
if (usedItemIdx.has(i))
|
|
896
|
+
continue;
|
|
897
|
+
if (itemTokens[i].startsWith(qt)) {
|
|
898
|
+
score += perTokenWeight;
|
|
899
|
+
usedItemIdx.add(i);
|
|
900
|
+
break;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
return score;
|
|
905
|
+
}
|
|
906
|
+
function scoreOrderAndPresence(qTokens, itemTokens, weights) {
|
|
907
|
+
const orderedWeight = weights?.ordered ?? 30;
|
|
908
|
+
const presenceWeight = weights?.presence ?? 10;
|
|
909
|
+
if (qTokens.length === 0 || itemTokens.length === 0)
|
|
910
|
+
return 0;
|
|
911
|
+
const matchedQueryIndices = new Set;
|
|
912
|
+
let qi = 0;
|
|
913
|
+
let score = 0;
|
|
914
|
+
for (let i = 0;i < itemTokens.length && qi < qTokens.length; i++) {
|
|
915
|
+
if (itemTokens[i].startsWith(qTokens[qi])) {
|
|
916
|
+
score += orderedWeight;
|
|
917
|
+
matchedQueryIndices.add(qi);
|
|
918
|
+
qi++;
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
if (matchedQueryIndices.size < qTokens.length) {
|
|
922
|
+
for (let qj = 0;qj < qTokens.length; qj++) {
|
|
923
|
+
if (matchedQueryIndices.has(qj))
|
|
924
|
+
continue;
|
|
925
|
+
const qt = qTokens[qj];
|
|
926
|
+
for (let i = 0;i < itemTokens.length; i++) {
|
|
927
|
+
if (itemTokens[i].startsWith(qt)) {
|
|
928
|
+
score += presenceWeight;
|
|
929
|
+
break;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
return score;
|
|
935
|
+
}
|
|
936
|
+
|
|
780
937
|
// src/common/numeric/searchInData.ts
|
|
781
938
|
function searchInDataReturnIdsNumeric(query, metadata, opts) {
|
|
782
939
|
return searchInDataReturnIdsWithLimitNumeric(query, metadata, Infinity, opts);
|
|
@@ -794,20 +951,48 @@ function searchInDataReturnObjectsNumeric(query, metadata, data, opts) {
|
|
|
794
951
|
}
|
|
795
952
|
function searchInDataReturnIdsWithLimitNumeric(query, metadata, limit, opts) {
|
|
796
953
|
const queryTokenStrs = prepareStringForSearch(query);
|
|
797
|
-
if (queryTokenStrs.length === 0)
|
|
954
|
+
if (queryTokenStrs.length === 0)
|
|
798
955
|
return [];
|
|
799
|
-
}
|
|
800
956
|
const preparedTokens = prepareQueryTokens(queryTokenStrs);
|
|
801
|
-
const
|
|
802
|
-
for (const [id, targetTokens] of metadata) {
|
|
957
|
+
const candidates = [];
|
|
958
|
+
for (const [id, targetTokens] of metadata.sorted) {
|
|
803
959
|
if (allPreparedTokensMatch(preparedTokens, targetTokens, opts)) {
|
|
804
|
-
|
|
805
|
-
if (results.length >= limit) {
|
|
806
|
-
break;
|
|
807
|
-
}
|
|
960
|
+
candidates.push(id);
|
|
808
961
|
}
|
|
809
962
|
}
|
|
810
|
-
|
|
963
|
+
if (candidates.length === 0)
|
|
964
|
+
return [];
|
|
965
|
+
const qTokens = orderedTokenize(query);
|
|
966
|
+
const hasUnsorted = metadata.unsorted.size > 0;
|
|
967
|
+
if (!hasUnsorted) {
|
|
968
|
+
if (limit === Infinity || limit >= candidates.length)
|
|
969
|
+
return candidates;
|
|
970
|
+
return candidates.slice(0, limit);
|
|
971
|
+
}
|
|
972
|
+
const scored = new Array(candidates.length);
|
|
973
|
+
for (let i = 0;i < candidates.length; i++) {
|
|
974
|
+
const id = candidates[i];
|
|
975
|
+
const unsortedIds = metadata.unsorted.get(id);
|
|
976
|
+
if (unsortedIds === undefined) {
|
|
977
|
+
scored[i] = { id, score: 0, order: i };
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
980
|
+
const itemTokens = new Array(unsortedIds.length);
|
|
981
|
+
for (let j = 0;j < unsortedIds.length; j++) {
|
|
982
|
+
itemTokens[j] = tokens[unsortedIds[j]] ?? "";
|
|
983
|
+
}
|
|
984
|
+
scored[i] = { id, score: scoreOne(query, qTokens, itemTokens), order: i };
|
|
985
|
+
}
|
|
986
|
+
scored.sort((a, b) => {
|
|
987
|
+
if (a.score !== b.score)
|
|
988
|
+
return b.score - a.score;
|
|
989
|
+
return a.order - b.order;
|
|
990
|
+
});
|
|
991
|
+
const out = [];
|
|
992
|
+
const max = limit === Infinity ? scored.length : Math.min(limit, scored.length);
|
|
993
|
+
for (let i = 0;i < max; i++)
|
|
994
|
+
out.push(scored[i].id);
|
|
995
|
+
return out;
|
|
811
996
|
}
|
|
812
997
|
// src/common/numeric/findInLinkedArrays.ts
|
|
813
998
|
function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
@@ -818,11 +1003,10 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
|
818
1003
|
const preparedTokens = prepareQueryTokens(queryTokenStrs);
|
|
819
1004
|
const positiveTokens = preparedTokens.filter((t) => !t.negated);
|
|
820
1005
|
const negatedTokens = preparedTokens.filter((t) => t.negated);
|
|
821
|
-
const
|
|
1006
|
+
const scored = [];
|
|
1007
|
+
let orderCounter = 0;
|
|
822
1008
|
for (const [primaryId, primary] of linked.primaryData) {
|
|
823
|
-
|
|
824
|
-
break;
|
|
825
|
-
const primaryTokens = linked.primaryMeta.get(primaryId);
|
|
1009
|
+
const primaryTokens = linked.primaryMeta.sorted.get(primaryId);
|
|
826
1010
|
if (!primaryTokens)
|
|
827
1011
|
continue;
|
|
828
1012
|
const linkedIds = linked.primaryToLinked.get(primaryId) || [];
|
|
@@ -833,22 +1017,20 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
|
833
1017
|
break;
|
|
834
1018
|
}
|
|
835
1019
|
}
|
|
836
|
-
if (negatedMatchesInPrimary)
|
|
1020
|
+
if (negatedMatchesInPrimary)
|
|
837
1021
|
continue;
|
|
838
|
-
}
|
|
839
1022
|
let totalLength = primaryTokens.length;
|
|
840
1023
|
for (const linkedId of linkedIds) {
|
|
841
|
-
const linkedTokens = linked.linkedMeta.get(linkedId);
|
|
842
|
-
if (linkedTokens)
|
|
1024
|
+
const linkedTokens = linked.linkedMeta.sorted.get(linkedId);
|
|
1025
|
+
if (linkedTokens)
|
|
843
1026
|
totalLength += linkedTokens.length;
|
|
844
|
-
}
|
|
845
1027
|
}
|
|
846
1028
|
const allTokens = new Uint32Array(totalLength);
|
|
847
1029
|
let offset = 0;
|
|
848
1030
|
allTokens.set(primaryTokens, offset);
|
|
849
1031
|
offset += primaryTokens.length;
|
|
850
1032
|
for (const linkedId of linkedIds) {
|
|
851
|
-
const linkedTokens = linked.linkedMeta.get(linkedId);
|
|
1033
|
+
const linkedTokens = linked.linkedMeta.sorted.get(linkedId);
|
|
852
1034
|
if (linkedTokens) {
|
|
853
1035
|
allTokens.set(linkedTokens, offset);
|
|
854
1036
|
offset += linkedTokens.length;
|
|
@@ -862,230 +1044,289 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
|
862
1044
|
break;
|
|
863
1045
|
}
|
|
864
1046
|
}
|
|
865
|
-
if (allPositiveMatch)
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
1047
|
+
if (!allPositiveMatch)
|
|
1048
|
+
continue;
|
|
1049
|
+
let anyMatchInPrimary = false;
|
|
1050
|
+
let anyMatchInLinked = false;
|
|
1051
|
+
const matchingLinkedIds = new Set;
|
|
1052
|
+
const tokensMatchingPrimary = new Set;
|
|
1053
|
+
for (const preparedToken of positiveTokens) {
|
|
1054
|
+
if (matchPreparedTokenInSortedList(preparedToken, primaryTokens, opts)) {
|
|
1055
|
+
anyMatchInPrimary = true;
|
|
1056
|
+
tokensMatchingPrimary.add(preparedToken);
|
|
875
1057
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
if (matchesNegatedToken) {
|
|
889
|
-
continue;
|
|
890
|
-
}
|
|
891
|
-
if (tokensForLinkedMatching.length > 0) {
|
|
892
|
-
const matchesAllNonPrimaryTokens = tokensForLinkedMatching.every((preparedToken) => matchPreparedTokenInSortedList(preparedToken, linkedTokens, opts));
|
|
893
|
-
if (matchesAllNonPrimaryTokens) {
|
|
894
|
-
anyMatchInLinked = true;
|
|
895
|
-
matchingLinkedIds.add(linkedId);
|
|
896
|
-
}
|
|
897
|
-
} else {
|
|
898
|
-
matchingLinkedIds.add(linkedId);
|
|
899
|
-
}
|
|
1058
|
+
}
|
|
1059
|
+
const tokensForLinkedMatching = positiveTokens.filter((t) => !tokensMatchingPrimary.has(t));
|
|
1060
|
+
if (tokensForLinkedMatching.length > 0 || negatedTokens.length > 0) {
|
|
1061
|
+
for (const linkedId of linkedIds) {
|
|
1062
|
+
const linkedTokens = linked.linkedMeta.sorted.get(linkedId);
|
|
1063
|
+
if (!linkedTokens)
|
|
1064
|
+
continue;
|
|
1065
|
+
let matchesNegatedToken = false;
|
|
1066
|
+
for (const negatedToken of negatedTokens) {
|
|
1067
|
+
if (matchPreparedTokenInSortedList(negatedToken, linkedTokens, opts)) {
|
|
1068
|
+
matchesNegatedToken = true;
|
|
1069
|
+
break;
|
|
900
1070
|
}
|
|
901
1071
|
}
|
|
1072
|
+
if (matchesNegatedToken)
|
|
1073
|
+
continue;
|
|
1074
|
+
if (tokensForLinkedMatching.length > 0) {
|
|
1075
|
+
const matchesAllNonPrimaryTokens = tokensForLinkedMatching.every((preparedToken) => matchPreparedTokenInSortedList(preparedToken, linkedTokens, opts));
|
|
1076
|
+
if (matchesAllNonPrimaryTokens) {
|
|
1077
|
+
anyMatchInLinked = true;
|
|
1078
|
+
matchingLinkedIds.add(linkedId);
|
|
1079
|
+
}
|
|
1080
|
+
} else {
|
|
1081
|
+
matchingLinkedIds.add(linkedId);
|
|
1082
|
+
}
|
|
902
1083
|
}
|
|
903
|
-
|
|
1084
|
+
}
|
|
1085
|
+
if (tokensForLinkedMatching.length > 0 && matchingLinkedIds.size === 0) {
|
|
1086
|
+
continue;
|
|
1087
|
+
}
|
|
1088
|
+
const matchedLinked = Array.from(matchingLinkedIds).map((id) => linked.linkedData.get(id)).filter((item) => item !== undefined);
|
|
1089
|
+
const result = {
|
|
1090
|
+
primary,
|
|
1091
|
+
linked: matchedLinked,
|
|
1092
|
+
matchedIn: anyMatchInPrimary && anyMatchInLinked ? "both" : anyMatchInPrimary ? "primary" : "linked"
|
|
1093
|
+
};
|
|
1094
|
+
scored.push({
|
|
1095
|
+
result,
|
|
1096
|
+
score: 0,
|
|
1097
|
+
order: orderCounter++,
|
|
1098
|
+
primaryId,
|
|
1099
|
+
matchedLinkedIds: Array.from(matchingLinkedIds)
|
|
1100
|
+
});
|
|
1101
|
+
}
|
|
1102
|
+
if (scored.length === 0) {
|
|
1103
|
+
return { queryTokens: queryTokenStrs, results: [], hasNegation: negatedTokens.length > 0 };
|
|
1104
|
+
}
|
|
1105
|
+
const qTokens = orderedTokenize(query);
|
|
1106
|
+
const hasUnsorted = linked.primaryMeta.unsorted.size > 0 || linked.linkedMeta.unsorted.size > 0;
|
|
1107
|
+
if (hasUnsorted) {
|
|
1108
|
+
for (const s of scored) {
|
|
1109
|
+
const itemTokenIds = [];
|
|
1110
|
+
const pu = linked.primaryMeta.unsorted.get(s.primaryId);
|
|
1111
|
+
if (pu)
|
|
1112
|
+
for (const tid of pu)
|
|
1113
|
+
itemTokenIds.push(tid);
|
|
1114
|
+
for (const lid of s.matchedLinkedIds) {
|
|
1115
|
+
const lu = linked.linkedMeta.unsorted.get(lid);
|
|
1116
|
+
if (lu)
|
|
1117
|
+
for (const tid of lu)
|
|
1118
|
+
itemTokenIds.push(tid);
|
|
1119
|
+
}
|
|
1120
|
+
if (itemTokenIds.length === 0) {
|
|
1121
|
+
s.score = 0;
|
|
904
1122
|
continue;
|
|
905
1123
|
}
|
|
906
|
-
const
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
});
|
|
1124
|
+
const itemTokens = new Array(itemTokenIds.length);
|
|
1125
|
+
for (let i = 0;i < itemTokenIds.length; i++) {
|
|
1126
|
+
itemTokens[i] = tokens[itemTokenIds[i]] ?? "";
|
|
1127
|
+
}
|
|
1128
|
+
s.score = scoreOne(query, qTokens, itemTokens);
|
|
912
1129
|
}
|
|
913
1130
|
}
|
|
1131
|
+
scored.sort((a, b) => {
|
|
1132
|
+
if (a.score !== b.score)
|
|
1133
|
+
return b.score - a.score;
|
|
1134
|
+
return a.order - b.order;
|
|
1135
|
+
});
|
|
1136
|
+
const max = Math.min(limit, scored.length);
|
|
1137
|
+
const results = new Array(max);
|
|
1138
|
+
for (let i = 0;i < max; i++)
|
|
1139
|
+
results[i] = scored[i].result;
|
|
914
1140
|
return { queryTokens: queryTokenStrs, results, hasNegation: negatedTokens.length > 0 };
|
|
915
1141
|
}
|
|
916
1142
|
function findInLinkedArraysSimpleNumeric(query, linked, limit = 10, opts) {
|
|
917
1143
|
return findInLinkedArraysNumeric(query, linked, limit, opts).results;
|
|
918
1144
|
}
|
|
919
1145
|
// src/common/numeric/AugmentedMetadata.ts
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
if (
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
if (tokens2 && tokens2.length > 0) {
|
|
940
|
-
this.augmentedTokens.set(id, tokens2);
|
|
1146
|
+
function mergeSortedTokenArrays(a, b) {
|
|
1147
|
+
const merged = new Uint32Array(a.length + b.length);
|
|
1148
|
+
let i = 0, j = 0, k = 0;
|
|
1149
|
+
let lastToken = -1;
|
|
1150
|
+
while (i < a.length && j < b.length) {
|
|
1151
|
+
const tokenA = a[i];
|
|
1152
|
+
const tokenB = b[j];
|
|
1153
|
+
if (tokenA < tokenB) {
|
|
1154
|
+
if (tokenA !== lastToken) {
|
|
1155
|
+
merged[k++] = tokenA;
|
|
1156
|
+
lastToken = tokenA;
|
|
1157
|
+
}
|
|
1158
|
+
i++;
|
|
1159
|
+
} else if (tokenA > tokenB) {
|
|
1160
|
+
if (tokenB !== lastToken) {
|
|
1161
|
+
merged[k++] = tokenB;
|
|
1162
|
+
lastToken = tokenB;
|
|
1163
|
+
}
|
|
1164
|
+
j++;
|
|
941
1165
|
} else {
|
|
942
|
-
|
|
1166
|
+
if (tokenA !== lastToken) {
|
|
1167
|
+
merged[k++] = tokenA;
|
|
1168
|
+
lastToken = tokenA;
|
|
1169
|
+
}
|
|
1170
|
+
i++;
|
|
1171
|
+
j++;
|
|
943
1172
|
}
|
|
944
|
-
clearTokensMap(tokensMap);
|
|
945
1173
|
}
|
|
946
|
-
|
|
947
|
-
const
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
continue;
|
|
952
|
-
}
|
|
953
|
-
const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
954
|
-
if (tokens2 && tokens2.length > 0) {
|
|
955
|
-
this.augmentedTokens.set(id, tokens2);
|
|
956
|
-
} else {
|
|
957
|
-
this.augmentedTokens.delete(id);
|
|
958
|
-
}
|
|
1174
|
+
while (i < a.length) {
|
|
1175
|
+
const tokenA = a[i];
|
|
1176
|
+
if (tokenA !== lastToken) {
|
|
1177
|
+
merged[k++] = tokenA;
|
|
1178
|
+
lastToken = tokenA;
|
|
959
1179
|
}
|
|
960
|
-
|
|
1180
|
+
i++;
|
|
961
1181
|
}
|
|
962
|
-
|
|
963
|
-
|
|
1182
|
+
while (j < b.length) {
|
|
1183
|
+
const tokenB = b[j];
|
|
1184
|
+
if (tokenB !== lastToken) {
|
|
1185
|
+
merged[k++] = tokenB;
|
|
1186
|
+
lastToken = tokenB;
|
|
1187
|
+
}
|
|
1188
|
+
j++;
|
|
964
1189
|
}
|
|
965
|
-
|
|
966
|
-
|
|
1190
|
+
return merged.slice(0, k);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
class AugmentedSortedMap extends Map {
|
|
1194
|
+
base;
|
|
1195
|
+
augTokens;
|
|
1196
|
+
constructor(base, augTokens) {
|
|
1197
|
+
super();
|
|
1198
|
+
this.base = base;
|
|
1199
|
+
this.augTokens = augTokens;
|
|
967
1200
|
}
|
|
968
1201
|
get(id) {
|
|
969
|
-
const baseTokens = this.
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
if (
|
|
1202
|
+
const baseTokens = this.base.get(id);
|
|
1203
|
+
const augTokens = this.augTokens.get(id);
|
|
1204
|
+
if (baseTokens === undefined)
|
|
1205
|
+
return augTokens;
|
|
1206
|
+
if (augTokens === undefined)
|
|
974
1207
|
return baseTokens;
|
|
975
|
-
return
|
|
1208
|
+
return mergeSortedTokenArrays(baseTokens, augTokens);
|
|
976
1209
|
}
|
|
977
1210
|
has(id) {
|
|
978
|
-
return this.
|
|
1211
|
+
return this.base.has(id) || this.augTokens.has(id);
|
|
979
1212
|
}
|
|
980
1213
|
get size() {
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
const
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
if (baseResult.done) {
|
|
990
|
-
return { done: true, value: undefined };
|
|
991
|
-
}
|
|
992
|
-
const [id, baseTokens] = baseResult.value;
|
|
993
|
-
const augTokens = self.augmentedTokens.get(id);
|
|
994
|
-
const tokens2 = augTokens ? self.mergeSortedTokenArrays(baseTokens, augTokens) : baseTokens;
|
|
995
|
-
return { done: false, value: [id, tokens2] };
|
|
996
|
-
},
|
|
997
|
-
[Symbol.iterator]() {
|
|
998
|
-
return this;
|
|
999
|
-
},
|
|
1000
|
-
[Symbol.dispose]() {}
|
|
1001
|
-
};
|
|
1214
|
+
if (this.augTokens.size === 0)
|
|
1215
|
+
return this.base.size;
|
|
1216
|
+
let count = this.base.size;
|
|
1217
|
+
for (const id of this.augTokens.keys()) {
|
|
1218
|
+
if (!this.base.has(id))
|
|
1219
|
+
count++;
|
|
1220
|
+
}
|
|
1221
|
+
return count;
|
|
1002
1222
|
}
|
|
1003
1223
|
keys() {
|
|
1004
|
-
return this.
|
|
1224
|
+
return this.unionIdIterator();
|
|
1005
1225
|
}
|
|
1006
1226
|
values() {
|
|
1007
1227
|
const self = this;
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
return tokens2 ? { done: false, value: tokens2 } : { done: true, value: undefined };
|
|
1017
|
-
},
|
|
1018
|
-
[Symbol.iterator]() {
|
|
1019
|
-
return this;
|
|
1020
|
-
},
|
|
1021
|
-
[Symbol.dispose]() {}
|
|
1022
|
-
};
|
|
1228
|
+
function* gen() {
|
|
1229
|
+
for (const id of self.unionIdIterator()) {
|
|
1230
|
+
const tokens2 = self.get(id);
|
|
1231
|
+
if (tokens2 !== undefined)
|
|
1232
|
+
yield tokens2;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
return gen();
|
|
1023
1236
|
}
|
|
1024
1237
|
entries() {
|
|
1025
|
-
|
|
1238
|
+
const self = this;
|
|
1239
|
+
function* gen() {
|
|
1240
|
+
for (const id of self.unionIdIterator()) {
|
|
1241
|
+
const tokens2 = self.get(id);
|
|
1242
|
+
if (tokens2 !== undefined)
|
|
1243
|
+
yield [id, tokens2];
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
return gen();
|
|
1247
|
+
}
|
|
1248
|
+
[Symbol.iterator]() {
|
|
1249
|
+
return this.entries();
|
|
1026
1250
|
}
|
|
1027
1251
|
forEach(callbackfn) {
|
|
1028
|
-
for (const [id, tokens2] of this) {
|
|
1252
|
+
for (const [id, tokens2] of this.entries()) {
|
|
1029
1253
|
callbackfn(tokens2, id, this);
|
|
1030
1254
|
}
|
|
1031
1255
|
}
|
|
1032
1256
|
set(_key, _value) {
|
|
1033
|
-
throw new Error("AugmentedMetadata.
|
|
1257
|
+
throw new Error("AugmentedMetadata.sorted is read-only. Use updateAugmented() instead.");
|
|
1034
1258
|
}
|
|
1035
1259
|
delete(_key) {
|
|
1036
|
-
throw new Error("AugmentedMetadata.
|
|
1260
|
+
throw new Error("AugmentedMetadata.sorted is read-only. Use clearAugmented() instead.");
|
|
1037
1261
|
}
|
|
1038
1262
|
clear() {
|
|
1039
|
-
throw new Error("AugmentedMetadata.
|
|
1263
|
+
throw new Error("AugmentedMetadata.sorted is read-only. Use clearAllAugmented() instead.");
|
|
1040
1264
|
}
|
|
1041
1265
|
get [Symbol.toStringTag]() {
|
|
1042
|
-
return "
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
const tokenA = a[i];
|
|
1050
|
-
const tokenB = b[j];
|
|
1051
|
-
if (tokenA < tokenB) {
|
|
1052
|
-
if (tokenA !== lastToken) {
|
|
1053
|
-
merged[k++] = tokenA;
|
|
1054
|
-
lastToken = tokenA;
|
|
1055
|
-
}
|
|
1056
|
-
i++;
|
|
1057
|
-
} else if (tokenA > tokenB) {
|
|
1058
|
-
if (tokenB !== lastToken) {
|
|
1059
|
-
merged[k++] = tokenB;
|
|
1060
|
-
lastToken = tokenB;
|
|
1061
|
-
}
|
|
1062
|
-
j++;
|
|
1063
|
-
} else {
|
|
1064
|
-
if (tokenA !== lastToken) {
|
|
1065
|
-
merged[k++] = tokenA;
|
|
1066
|
-
lastToken = tokenA;
|
|
1067
|
-
}
|
|
1068
|
-
i++;
|
|
1069
|
-
j++;
|
|
1070
|
-
}
|
|
1266
|
+
return "AugmentedSortedMap";
|
|
1267
|
+
}
|
|
1268
|
+
*unionIdIterator() {
|
|
1269
|
+
const seen = new Set;
|
|
1270
|
+
for (const id of this.base.keys()) {
|
|
1271
|
+
seen.add(id);
|
|
1272
|
+
yield id;
|
|
1071
1273
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
merged[k++] = tokenA;
|
|
1076
|
-
lastToken = tokenA;
|
|
1077
|
-
}
|
|
1078
|
-
i++;
|
|
1274
|
+
for (const id of this.augTokens.keys()) {
|
|
1275
|
+
if (!seen.has(id))
|
|
1276
|
+
yield id;
|
|
1079
1277
|
}
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
class AugmentedMetadata {
|
|
1282
|
+
sorted;
|
|
1283
|
+
unsorted;
|
|
1284
|
+
augmentedTokens;
|
|
1285
|
+
spec;
|
|
1286
|
+
constructor(baseMetadata, spec, augmentedDataMap) {
|
|
1287
|
+
this.augmentedTokens = new Map;
|
|
1288
|
+
this.spec = spec;
|
|
1289
|
+
this.sorted = new AugmentedSortedMap(baseMetadata.sorted, this.augmentedTokens);
|
|
1290
|
+
this.unsorted = baseMetadata.unsorted;
|
|
1291
|
+
if (augmentedDataMap && augmentedDataMap.size > 0) {
|
|
1292
|
+
this.updateAugmentedBatch(augmentedDataMap);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
updateAugmented(id, augmentedData) {
|
|
1296
|
+
if (augmentedData == null) {
|
|
1297
|
+
this.augmentedTokens.delete(id);
|
|
1298
|
+
return;
|
|
1299
|
+
}
|
|
1300
|
+
const tokensMap = createTokensMap();
|
|
1301
|
+
const prepared = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
1302
|
+
clearTokensMap(tokensMap);
|
|
1303
|
+
if (prepared !== undefined && prepared.sorted.length > 0) {
|
|
1304
|
+
this.augmentedTokens.set(id, prepared.sorted);
|
|
1305
|
+
} else {
|
|
1306
|
+
this.augmentedTokens.delete(id);
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
updateAugmentedBatch(augmentedDataMap) {
|
|
1310
|
+
const tokensMap = createTokensMap();
|
|
1311
|
+
for (const [id, augmentedData] of augmentedDataMap) {
|
|
1312
|
+
if (augmentedData == null) {
|
|
1313
|
+
this.augmentedTokens.delete(id);
|
|
1314
|
+
continue;
|
|
1315
|
+
}
|
|
1316
|
+
const prepared = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
1317
|
+
if (prepared !== undefined && prepared.sorted.length > 0) {
|
|
1318
|
+
this.augmentedTokens.set(id, prepared.sorted);
|
|
1319
|
+
} else {
|
|
1320
|
+
this.augmentedTokens.delete(id);
|
|
1085
1321
|
}
|
|
1086
|
-
j++;
|
|
1087
1322
|
}
|
|
1088
|
-
|
|
1323
|
+
clearTokensMap(tokensMap);
|
|
1324
|
+
}
|
|
1325
|
+
clearAugmented(id) {
|
|
1326
|
+
this.augmentedTokens.delete(id);
|
|
1327
|
+
}
|
|
1328
|
+
clearAllAugmented() {
|
|
1329
|
+
this.augmentedTokens.clear();
|
|
1089
1330
|
}
|
|
1090
1331
|
}
|
|
1091
1332
|
// src/common/numeric/syncSearchArrayMetadata.ts
|
|
@@ -1098,6 +1339,25 @@ function tokensEqual(a, b) {
|
|
|
1098
1339
|
}
|
|
1099
1340
|
return true;
|
|
1100
1341
|
}
|
|
1342
|
+
function firstNEqual(a, b) {
|
|
1343
|
+
if (a === undefined && b === undefined)
|
|
1344
|
+
return true;
|
|
1345
|
+
if (a === undefined || b === undefined)
|
|
1346
|
+
return false;
|
|
1347
|
+
return tokensEqual(a, b);
|
|
1348
|
+
}
|
|
1349
|
+
function applyPreparedTokens(metadata, id, result) {
|
|
1350
|
+
metadata.sorted.set(id, result.sorted);
|
|
1351
|
+
if (result.firstN !== undefined) {
|
|
1352
|
+
metadata.unsorted.set(id, result.firstN);
|
|
1353
|
+
} else {
|
|
1354
|
+
metadata.unsorted.delete(id);
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
function deletePreparedTokens(metadata, id) {
|
|
1358
|
+
metadata.sorted.delete(id);
|
|
1359
|
+
metadata.unsorted.delete(id);
|
|
1360
|
+
}
|
|
1101
1361
|
function syncSearchArrayMetadataNumeric(metadata, newData, spec) {
|
|
1102
1362
|
const result = {
|
|
1103
1363
|
added: 0,
|
|
@@ -1108,30 +1368,31 @@ function syncSearchArrayMetadataNumeric(metadata, newData, spec) {
|
|
|
1108
1368
|
removedIds: []
|
|
1109
1369
|
};
|
|
1110
1370
|
const tokensMap = createTokensMap();
|
|
1111
|
-
for (const id of metadata.keys()) {
|
|
1371
|
+
for (const id of metadata.sorted.keys()) {
|
|
1112
1372
|
if (!newData.has(id)) {
|
|
1113
|
-
metadata
|
|
1373
|
+
deletePreparedTokens(metadata, id);
|
|
1114
1374
|
result.removed++;
|
|
1115
1375
|
result.removedIds.push(id);
|
|
1116
1376
|
}
|
|
1117
1377
|
}
|
|
1118
1378
|
for (const [id, item] of newData) {
|
|
1119
|
-
const
|
|
1120
|
-
if (
|
|
1121
|
-
if (metadata.has(id)) {
|
|
1122
|
-
metadata
|
|
1379
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1380
|
+
if (prepared === undefined) {
|
|
1381
|
+
if (metadata.sorted.has(id)) {
|
|
1382
|
+
deletePreparedTokens(metadata, id);
|
|
1123
1383
|
result.removed++;
|
|
1124
1384
|
result.removedIds.push(id);
|
|
1125
1385
|
}
|
|
1126
1386
|
continue;
|
|
1127
1387
|
}
|
|
1128
|
-
const
|
|
1129
|
-
|
|
1130
|
-
|
|
1388
|
+
const existingSorted = metadata.sorted.get(id);
|
|
1389
|
+
const existingFirstN = metadata.unsorted.get(id);
|
|
1390
|
+
if (existingSorted === undefined) {
|
|
1391
|
+
applyPreparedTokens(metadata, id, prepared);
|
|
1131
1392
|
result.added++;
|
|
1132
1393
|
result.addedIds.push(id);
|
|
1133
|
-
} else if (!tokensEqual(
|
|
1134
|
-
metadata
|
|
1394
|
+
} else if (!tokensEqual(existingSorted, prepared.sorted) || !firstNEqual(existingFirstN, prepared.firstN)) {
|
|
1395
|
+
applyPreparedTokens(metadata, id, prepared);
|
|
1135
1396
|
result.updated++;
|
|
1136
1397
|
result.updatedIds.push(id);
|
|
1137
1398
|
}
|
|
@@ -1151,7 +1412,7 @@ function syncSearchArrayMetadataNumericWithPrevious(metadata, previousData, newD
|
|
|
1151
1412
|
const tokensMap = createTokensMap();
|
|
1152
1413
|
for (const id of previousData.keys()) {
|
|
1153
1414
|
if (!newData.has(id)) {
|
|
1154
|
-
metadata
|
|
1415
|
+
deletePreparedTokens(metadata, id);
|
|
1155
1416
|
result.removed++;
|
|
1156
1417
|
result.removedIds.push(id);
|
|
1157
1418
|
}
|
|
@@ -1159,22 +1420,23 @@ function syncSearchArrayMetadataNumericWithPrevious(metadata, previousData, newD
|
|
|
1159
1420
|
for (const [id, item] of newData) {
|
|
1160
1421
|
const wasInPrevious = previousData.has(id);
|
|
1161
1422
|
if (!wasInPrevious) {
|
|
1162
|
-
const
|
|
1163
|
-
if (
|
|
1164
|
-
metadata
|
|
1423
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1424
|
+
if (prepared !== undefined) {
|
|
1425
|
+
applyPreparedTokens(metadata, id, prepared);
|
|
1165
1426
|
result.added++;
|
|
1166
1427
|
result.addedIds.push(id);
|
|
1167
1428
|
}
|
|
1168
1429
|
} else if (!options?.skipUpdateCheck) {
|
|
1169
|
-
const
|
|
1170
|
-
if (
|
|
1171
|
-
metadata
|
|
1430
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1431
|
+
if (prepared === undefined) {
|
|
1432
|
+
deletePreparedTokens(metadata, id);
|
|
1172
1433
|
result.removed++;
|
|
1173
1434
|
result.removedIds.push(id);
|
|
1174
1435
|
} else {
|
|
1175
|
-
const
|
|
1176
|
-
|
|
1177
|
-
|
|
1436
|
+
const existingSorted = metadata.sorted.get(id);
|
|
1437
|
+
const existingFirstN = metadata.unsorted.get(id);
|
|
1438
|
+
if (existingSorted && (!tokensEqual(existingSorted, prepared.sorted) || !firstNEqual(existingFirstN, prepared.firstN))) {
|
|
1439
|
+
applyPreparedTokens(metadata, id, prepared);
|
|
1178
1440
|
result.updated++;
|
|
1179
1441
|
result.updatedIds.push(id);
|
|
1180
1442
|
}
|
|
@@ -1194,29 +1456,48 @@ function tokensEqual2(a, b) {
|
|
|
1194
1456
|
}
|
|
1195
1457
|
return true;
|
|
1196
1458
|
}
|
|
1459
|
+
function firstNEqual2(a, b) {
|
|
1460
|
+
if (a === undefined && b === undefined)
|
|
1461
|
+
return true;
|
|
1462
|
+
if (a === undefined || b === undefined)
|
|
1463
|
+
return false;
|
|
1464
|
+
return tokensEqual2(a, b);
|
|
1465
|
+
}
|
|
1466
|
+
function applyOrClear(meta, id, prepared) {
|
|
1467
|
+
if (prepared === undefined) {
|
|
1468
|
+
meta.sorted.delete(id);
|
|
1469
|
+
meta.unsorted.delete(id);
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
meta.sorted.set(id, prepared.sorted);
|
|
1473
|
+
if (prepared.firstN !== undefined) {
|
|
1474
|
+
meta.unsorted.set(id, prepared.firstN);
|
|
1475
|
+
} else {
|
|
1476
|
+
meta.unsorted.delete(id);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
function clearTokens(meta, id) {
|
|
1480
|
+
meta.sorted.delete(id);
|
|
1481
|
+
meta.unsorted.delete(id);
|
|
1482
|
+
}
|
|
1197
1483
|
function upsertPrimaryItemNumeric(linked, item, spec) {
|
|
1198
1484
|
const id = item._id;
|
|
1199
1485
|
const wasAdded = !linked.primaryData.has(id);
|
|
1200
1486
|
linked.primaryData.set(id, item);
|
|
1201
1487
|
const tokensMap = createTokensMap();
|
|
1202
|
-
const
|
|
1488
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1203
1489
|
clearTokensMap(tokensMap);
|
|
1204
|
-
|
|
1205
|
-
linked.primaryMeta.set(id, tokens2);
|
|
1206
|
-
} else {
|
|
1207
|
-
linked.primaryMeta.delete(id);
|
|
1208
|
-
}
|
|
1490
|
+
applyOrClear(linked.primaryMeta, id, prepared);
|
|
1209
1491
|
if (wasAdded && !linked.primaryToLinked.has(id)) {
|
|
1210
1492
|
linked.primaryToLinked.set(id, []);
|
|
1211
1493
|
}
|
|
1212
1494
|
return { added: wasAdded };
|
|
1213
1495
|
}
|
|
1214
1496
|
function removePrimaryItemNumeric(linked, primaryId) {
|
|
1215
|
-
if (!linked.primaryData.has(primaryId))
|
|
1497
|
+
if (!linked.primaryData.has(primaryId))
|
|
1216
1498
|
return false;
|
|
1217
|
-
}
|
|
1218
1499
|
linked.primaryData.delete(primaryId);
|
|
1219
|
-
linked.primaryMeta
|
|
1500
|
+
clearTokens(linked.primaryMeta, primaryId);
|
|
1220
1501
|
linked.primaryToLinked.delete(primaryId);
|
|
1221
1502
|
return true;
|
|
1222
1503
|
}
|
|
@@ -1225,35 +1506,28 @@ function upsertLinkedItemNumeric(linked, item, foreignKeyGetter, spec) {
|
|
|
1225
1506
|
const newPrimaryId = foreignKeyGetter(item);
|
|
1226
1507
|
let previousPrimaryId;
|
|
1227
1508
|
const existingItem = linked.linkedData.get(id);
|
|
1228
|
-
if (existingItem)
|
|
1509
|
+
if (existingItem)
|
|
1229
1510
|
previousPrimaryId = foreignKeyGetter(existingItem);
|
|
1230
|
-
}
|
|
1231
1511
|
const wasAdded = !existingItem;
|
|
1232
1512
|
linked.linkedData.set(id, item);
|
|
1233
1513
|
const tokensMap = createTokensMap();
|
|
1234
|
-
const
|
|
1514
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1235
1515
|
clearTokensMap(tokensMap);
|
|
1236
|
-
|
|
1237
|
-
linked.linkedMeta.set(id, tokens2);
|
|
1238
|
-
} else {
|
|
1239
|
-
linked.linkedMeta.delete(id);
|
|
1240
|
-
}
|
|
1516
|
+
applyOrClear(linked.linkedMeta, id, prepared);
|
|
1241
1517
|
if (previousPrimaryId !== newPrimaryId) {
|
|
1242
1518
|
if (previousPrimaryId) {
|
|
1243
1519
|
const oldList = linked.primaryToLinked.get(previousPrimaryId);
|
|
1244
1520
|
if (oldList) {
|
|
1245
1521
|
const index = oldList.indexOf(id);
|
|
1246
|
-
if (index !== -1)
|
|
1522
|
+
if (index !== -1)
|
|
1247
1523
|
oldList.splice(index, 1);
|
|
1248
|
-
}
|
|
1249
1524
|
}
|
|
1250
1525
|
}
|
|
1251
1526
|
if (newPrimaryId) {
|
|
1252
1527
|
const newList = linked.primaryToLinked.get(newPrimaryId);
|
|
1253
1528
|
if (newList) {
|
|
1254
|
-
if (!newList.includes(id))
|
|
1529
|
+
if (!newList.includes(id))
|
|
1255
1530
|
newList.push(id);
|
|
1256
|
-
}
|
|
1257
1531
|
} else {
|
|
1258
1532
|
linked.primaryToLinked.set(newPrimaryId, [id]);
|
|
1259
1533
|
}
|
|
@@ -1266,64 +1540,57 @@ function upsertLinkedItemNumeric(linked, item, foreignKeyGetter, spec) {
|
|
|
1266
1540
|
}
|
|
1267
1541
|
function removeLinkedItemNumeric(linked, linkedId, foreignKeyGetter) {
|
|
1268
1542
|
const existingItem = linked.linkedData.get(linkedId);
|
|
1269
|
-
if (!existingItem)
|
|
1543
|
+
if (!existingItem)
|
|
1270
1544
|
return false;
|
|
1271
|
-
}
|
|
1272
1545
|
const primaryId = foreignKeyGetter(existingItem);
|
|
1273
1546
|
linked.linkedData.delete(linkedId);
|
|
1274
|
-
linked.linkedMeta
|
|
1547
|
+
clearTokens(linked.linkedMeta, linkedId);
|
|
1275
1548
|
if (primaryId) {
|
|
1276
1549
|
const list = linked.primaryToLinked.get(primaryId);
|
|
1277
1550
|
if (list) {
|
|
1278
1551
|
const index = list.indexOf(linkedId);
|
|
1279
|
-
if (index !== -1)
|
|
1552
|
+
if (index !== -1)
|
|
1280
1553
|
list.splice(index, 1);
|
|
1281
|
-
}
|
|
1282
1554
|
}
|
|
1283
1555
|
}
|
|
1284
1556
|
return true;
|
|
1285
1557
|
}
|
|
1286
1558
|
function syncLinkedItemsForPrimaryNumeric(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
|
|
1287
|
-
const result = {
|
|
1288
|
-
added: 0,
|
|
1289
|
-
updated: 0,
|
|
1290
|
-
removed: 0
|
|
1291
|
-
};
|
|
1559
|
+
const result = { added: 0, updated: 0, removed: 0 };
|
|
1292
1560
|
const tokensMap = createTokensMap();
|
|
1293
1561
|
const currentLinkedIds = new Set(linked.primaryToLinked.get(primaryId) || []);
|
|
1294
1562
|
const newLinkedIds = new Set;
|
|
1295
1563
|
for (const [id, item] of newLinkedItems) {
|
|
1296
|
-
if (foreignKeyGetter(item) === primaryId)
|
|
1564
|
+
if (foreignKeyGetter(item) === primaryId)
|
|
1297
1565
|
newLinkedIds.add(id);
|
|
1298
|
-
}
|
|
1299
1566
|
}
|
|
1300
1567
|
for (const id of currentLinkedIds) {
|
|
1301
1568
|
if (!newLinkedIds.has(id)) {
|
|
1302
|
-
|
|
1303
|
-
if (item) {
|
|
1569
|
+
if (linked.linkedData.has(id)) {
|
|
1304
1570
|
linked.linkedData.delete(id);
|
|
1305
|
-
linked.linkedMeta
|
|
1571
|
+
clearTokens(linked.linkedMeta, id);
|
|
1306
1572
|
result.removed++;
|
|
1307
1573
|
}
|
|
1308
1574
|
}
|
|
1309
1575
|
}
|
|
1310
1576
|
for (const id of newLinkedIds) {
|
|
1311
1577
|
const item = newLinkedItems.get(id);
|
|
1312
|
-
const
|
|
1578
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1313
1579
|
if (currentLinkedIds.has(id)) {
|
|
1314
|
-
const
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1580
|
+
const existingSorted = linked.linkedMeta.sorted.get(id);
|
|
1581
|
+
const existingFirstN = linked.linkedMeta.unsorted.get(id);
|
|
1582
|
+
if (prepared !== undefined) {
|
|
1583
|
+
if (!existingSorted || !tokensEqual2(existingSorted, prepared.sorted) || !firstNEqual2(existingFirstN, prepared.firstN)) {
|
|
1584
|
+
applyOrClear(linked.linkedMeta, id, prepared);
|
|
1318
1585
|
result.updated++;
|
|
1319
1586
|
}
|
|
1587
|
+
} else {
|
|
1588
|
+
clearTokens(linked.linkedMeta, id);
|
|
1320
1589
|
}
|
|
1321
1590
|
linked.linkedData.set(id, item);
|
|
1322
1591
|
} else {
|
|
1323
1592
|
linked.linkedData.set(id, item);
|
|
1324
|
-
|
|
1325
|
-
linked.linkedMeta.set(id, tokens2);
|
|
1326
|
-
}
|
|
1593
|
+
applyOrClear(linked.linkedMeta, id, prepared);
|
|
1327
1594
|
result.added++;
|
|
1328
1595
|
}
|
|
1329
1596
|
}
|
|
@@ -1331,6 +1598,43 @@ function syncLinkedItemsForPrimaryNumeric(linked, primaryId, newLinkedItems, for
|
|
|
1331
1598
|
clearTokensMap(tokensMap);
|
|
1332
1599
|
return result;
|
|
1333
1600
|
}
|
|
1601
|
+
// src/common/numeric/searchAndRank.ts
|
|
1602
|
+
function tokenIdsToStrings(tokenIds) {
|
|
1603
|
+
if (tokenIds === undefined)
|
|
1604
|
+
return;
|
|
1605
|
+
const out = new Array(tokenIds.length);
|
|
1606
|
+
for (let i = 0;i < tokenIds.length; i++) {
|
|
1607
|
+
out[i] = tokens[tokenIds[i]] ?? "";
|
|
1608
|
+
}
|
|
1609
|
+
return out;
|
|
1610
|
+
}
|
|
1611
|
+
function searchAndRankNumeric(query, data, metadata, options) {
|
|
1612
|
+
const { primaryTextFn, exactKeysFn, limit, opts } = options;
|
|
1613
|
+
const ids = searchInDataReturnIdsNumeric(query, metadata, opts);
|
|
1614
|
+
if (ids.length === 0)
|
|
1615
|
+
return [];
|
|
1616
|
+
const qTokens = orderedTokenize(query);
|
|
1617
|
+
const scored = [];
|
|
1618
|
+
for (const id of ids) {
|
|
1619
|
+
const item = data.get(id);
|
|
1620
|
+
if (!item)
|
|
1621
|
+
continue;
|
|
1622
|
+
const itemTokens = tokenIdsToStrings(metadata.unsorted.get(id)) ?? orderedTokenize(primaryTextFn(item) || "");
|
|
1623
|
+
const exactKeys = exactKeysFn?.(item);
|
|
1624
|
+
const score = scoreOne(query, qTokens, itemTokens, exactKeys);
|
|
1625
|
+
scored.push({ id, item, score });
|
|
1626
|
+
}
|
|
1627
|
+
scored.sort((x, y) => {
|
|
1628
|
+
if (y.score !== x.score)
|
|
1629
|
+
return y.score - x.score;
|
|
1630
|
+
const xText = primaryTextFn(x.item) || "";
|
|
1631
|
+
const yText = primaryTextFn(y.item) || "";
|
|
1632
|
+
return xText.localeCompare(yText);
|
|
1633
|
+
});
|
|
1634
|
+
if (limit === undefined || limit === Infinity || limit >= scored.length)
|
|
1635
|
+
return scored;
|
|
1636
|
+
return scored.slice(0, limit);
|
|
1637
|
+
}
|
|
1334
1638
|
// src/common/SearchUniverse.ts
|
|
1335
1639
|
function tokensEqual3(a, b) {
|
|
1336
1640
|
if (a.length !== b.length)
|
|
@@ -1341,6 +1645,13 @@ function tokensEqual3(a, b) {
|
|
|
1341
1645
|
}
|
|
1342
1646
|
return true;
|
|
1343
1647
|
}
|
|
1648
|
+
function firstNEqual3(a, b) {
|
|
1649
|
+
if (a === undefined && b === undefined)
|
|
1650
|
+
return true;
|
|
1651
|
+
if (a === undefined || b === undefined)
|
|
1652
|
+
return false;
|
|
1653
|
+
return tokensEqual3(a, b);
|
|
1654
|
+
}
|
|
1344
1655
|
|
|
1345
1656
|
class SearchUniverse {
|
|
1346
1657
|
collections = new Map;
|
|
@@ -1350,7 +1661,7 @@ class SearchUniverse {
|
|
|
1350
1661
|
}
|
|
1351
1662
|
const collection = {
|
|
1352
1663
|
data: new Map,
|
|
1353
|
-
metadata:
|
|
1664
|
+
metadata: emptyNumericSearchMetadata(),
|
|
1354
1665
|
config
|
|
1355
1666
|
};
|
|
1356
1667
|
if (config.linkedTo) {
|
|
@@ -1367,7 +1678,8 @@ class SearchUniverse {
|
|
|
1367
1678
|
loadCollection(name, items) {
|
|
1368
1679
|
const collection = this.getCollectionOrThrow(name);
|
|
1369
1680
|
collection.data.clear();
|
|
1370
|
-
collection.metadata.clear();
|
|
1681
|
+
collection.metadata.sorted.clear();
|
|
1682
|
+
collection.metadata.unsorted.clear();
|
|
1371
1683
|
if (collection.primaryToLinked) {
|
|
1372
1684
|
collection.primaryToLinked.clear();
|
|
1373
1685
|
}
|
|
@@ -1375,8 +1687,11 @@ class SearchUniverse {
|
|
|
1375
1687
|
collection.data.set(item._id, item);
|
|
1376
1688
|
}
|
|
1377
1689
|
const newMetadata = createSearchArrayMetadataNumeric(collection.data, collection.config.spec);
|
|
1378
|
-
for (const [id, tokens2] of newMetadata) {
|
|
1379
|
-
collection.metadata.set(id, tokens2);
|
|
1690
|
+
for (const [id, tokens2] of newMetadata.sorted) {
|
|
1691
|
+
collection.metadata.sorted.set(id, tokens2);
|
|
1692
|
+
}
|
|
1693
|
+
for (const [id, tokens2] of newMetadata.unsorted) {
|
|
1694
|
+
collection.metadata.unsorted.set(id, tokens2);
|
|
1380
1695
|
}
|
|
1381
1696
|
if (collection.config.linkedTo && collection.primaryToLinked) {
|
|
1382
1697
|
const { foreignKeyGetter } = collection.config.linkedTo;
|
|
@@ -1472,11 +1787,17 @@ class SearchUniverse {
|
|
|
1472
1787
|
collection.data.set(id, item);
|
|
1473
1788
|
const tokensMap = createTokensMap();
|
|
1474
1789
|
try {
|
|
1475
|
-
const
|
|
1476
|
-
if (
|
|
1477
|
-
collection.metadata.set(id,
|
|
1790
|
+
const prepared = prepareObjectForSearchNumeric(item, collection.config.spec, tokensMap);
|
|
1791
|
+
if (prepared !== undefined) {
|
|
1792
|
+
collection.metadata.sorted.set(id, prepared.sorted);
|
|
1793
|
+
if (prepared.firstN !== undefined) {
|
|
1794
|
+
collection.metadata.unsorted.set(id, prepared.firstN);
|
|
1795
|
+
} else {
|
|
1796
|
+
collection.metadata.unsorted.delete(id);
|
|
1797
|
+
}
|
|
1478
1798
|
} else {
|
|
1479
|
-
collection.metadata.delete(id);
|
|
1799
|
+
collection.metadata.sorted.delete(id);
|
|
1800
|
+
collection.metadata.unsorted.delete(id);
|
|
1480
1801
|
}
|
|
1481
1802
|
} finally {
|
|
1482
1803
|
clearTokensMap(tokensMap);
|
|
@@ -1530,7 +1851,8 @@ class SearchUniverse {
|
|
|
1530
1851
|
}
|
|
1531
1852
|
}
|
|
1532
1853
|
collection.data.delete(id);
|
|
1533
|
-
collection.metadata.delete(id);
|
|
1854
|
+
collection.metadata.sorted.delete(id);
|
|
1855
|
+
collection.metadata.unsorted.delete(id);
|
|
1534
1856
|
return true;
|
|
1535
1857
|
}
|
|
1536
1858
|
removeFromSearchMetadataBatch(collectionName, ids) {
|
|
@@ -1581,9 +1903,10 @@ class SearchUniverse {
|
|
|
1581
1903
|
}
|
|
1582
1904
|
}
|
|
1583
1905
|
}
|
|
1584
|
-
const hadMetadata = collection.metadata.has(id);
|
|
1906
|
+
const hadMetadata = collection.metadata.sorted.has(id);
|
|
1585
1907
|
collection.data.delete(id);
|
|
1586
|
-
collection.metadata.delete(id);
|
|
1908
|
+
collection.metadata.sorted.delete(id);
|
|
1909
|
+
collection.metadata.unsorted.delete(id);
|
|
1587
1910
|
if (hadMetadata) {
|
|
1588
1911
|
result.removed++;
|
|
1589
1912
|
result.removedIds.push(id);
|
|
@@ -1594,11 +1917,11 @@ class SearchUniverse {
|
|
|
1594
1917
|
for (const item of newItems) {
|
|
1595
1918
|
const id = item._id;
|
|
1596
1919
|
const existing = collection.data.get(id);
|
|
1597
|
-
const hadMetadata = collection.metadata.has(id);
|
|
1920
|
+
const hadMetadata = collection.metadata.sorted.has(id);
|
|
1598
1921
|
const shouldTokenize = !existing || !skipUpdateCheck;
|
|
1599
|
-
let
|
|
1922
|
+
let prepared;
|
|
1600
1923
|
if (shouldTokenize) {
|
|
1601
|
-
|
|
1924
|
+
prepared = prepareObjectForSearchNumeric(item, collection.config.spec, tokensMap);
|
|
1602
1925
|
}
|
|
1603
1926
|
if (fkGetter && collection.primaryToLinked) {
|
|
1604
1927
|
const newFk = fkGetter(item);
|
|
@@ -1628,20 +1951,30 @@ class SearchUniverse {
|
|
|
1628
1951
|
collection.data.set(id, item);
|
|
1629
1952
|
if (!shouldTokenize)
|
|
1630
1953
|
continue;
|
|
1631
|
-
if (
|
|
1954
|
+
if (prepared === undefined) {
|
|
1632
1955
|
if (hadMetadata) {
|
|
1633
|
-
collection.metadata.delete(id);
|
|
1956
|
+
collection.metadata.sorted.delete(id);
|
|
1957
|
+
collection.metadata.unsorted.delete(id);
|
|
1634
1958
|
result.removed++;
|
|
1635
1959
|
result.removedIds.push(id);
|
|
1636
1960
|
}
|
|
1637
1961
|
} else if (!hadMetadata) {
|
|
1638
|
-
collection.metadata.set(id,
|
|
1962
|
+
collection.metadata.sorted.set(id, prepared.sorted);
|
|
1963
|
+
if (prepared.firstN !== undefined) {
|
|
1964
|
+
collection.metadata.unsorted.set(id, prepared.firstN);
|
|
1965
|
+
}
|
|
1639
1966
|
result.added++;
|
|
1640
1967
|
result.addedIds.push(id);
|
|
1641
1968
|
} else {
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1644
|
-
|
|
1969
|
+
const existingSorted = collection.metadata.sorted.get(id);
|
|
1970
|
+
const existingFirstN = collection.metadata.unsorted.get(id);
|
|
1971
|
+
if (!tokensEqual3(existingSorted, prepared.sorted) || !firstNEqual3(existingFirstN, prepared.firstN)) {
|
|
1972
|
+
collection.metadata.sorted.set(id, prepared.sorted);
|
|
1973
|
+
if (prepared.firstN !== undefined) {
|
|
1974
|
+
collection.metadata.unsorted.set(id, prepared.firstN);
|
|
1975
|
+
} else {
|
|
1976
|
+
collection.metadata.unsorted.delete(id);
|
|
1977
|
+
}
|
|
1645
1978
|
result.updated++;
|
|
1646
1979
|
result.updatedIds.push(id);
|
|
1647
1980
|
}
|
|
@@ -1720,7 +2053,8 @@ class SearchUniverse {
|
|
|
1720
2053
|
clear() {
|
|
1721
2054
|
for (const collection of this.collections.values()) {
|
|
1722
2055
|
collection.data.clear();
|
|
1723
|
-
collection.metadata.clear();
|
|
2056
|
+
collection.metadata.sorted.clear();
|
|
2057
|
+
collection.metadata.unsorted.clear();
|
|
1724
2058
|
if (collection.primaryToLinked) {
|
|
1725
2059
|
collection.primaryToLinked.clear();
|
|
1726
2060
|
}
|