cry-search 1.0.7 → 2.0.0
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 +73 -98
- package/README.md +39 -28
- package/UNIVERSE.md +11 -18
- 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 +18 -60
- package/dist/common/numeric/searchAndRank.d.ts.map +1 -1
- 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 +614 -360
- package/dist/index.d.cts +3 -4
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +614 -360
- 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.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/types/index.ts
|
|
2
|
+
var DEFAULT_FIRST_TOKENS_N = 8;
|
|
2
3
|
var DEFAULT_SEARCH_OPTS = {
|
|
3
4
|
matchWords: "start",
|
|
4
5
|
matchNumbers: "startEnd",
|
|
@@ -268,11 +269,23 @@ function prepareStringForSearchNumeric(input, tokensMap) {
|
|
|
268
269
|
for (let i = 0;i < stringTokens.length; i++) {
|
|
269
270
|
numericTokens[i] = getOrCreateTokenId(stringTokens[i], tokensMap);
|
|
270
271
|
}
|
|
271
|
-
|
|
272
|
-
|
|
272
|
+
const unsorted = Uint32Array.from(numericTokens);
|
|
273
|
+
const sortedArr = numericTokens.slice().sort((a, b) => a - b);
|
|
274
|
+
const sorted = Uint32Array.from(sortedArr);
|
|
275
|
+
return { sorted, unsorted };
|
|
273
276
|
}
|
|
274
277
|
|
|
275
|
-
// src/common/
|
|
278
|
+
// src/common/numeric/createSearchArrayMetadata.ts
|
|
279
|
+
function isDeletedOrBlocked(obj) {
|
|
280
|
+
return obj._deleted != null || obj._blocked != null;
|
|
281
|
+
}
|
|
282
|
+
var MATCH_MODE_PREFIXES = {
|
|
283
|
+
start: "<",
|
|
284
|
+
end: ">",
|
|
285
|
+
startEnd: "+",
|
|
286
|
+
anywhere: "*",
|
|
287
|
+
whole: "!"
|
|
288
|
+
};
|
|
276
289
|
var PREFIX_TO_MATCH_MODE = {
|
|
277
290
|
"<": "start",
|
|
278
291
|
">": "end",
|
|
@@ -282,12 +295,6 @@ var PREFIX_TO_MATCH_MODE = {
|
|
|
282
295
|
"=": "whole",
|
|
283
296
|
"?": "anywhere"
|
|
284
297
|
};
|
|
285
|
-
var DEFAULT_EXCLUDED_FIELDS = new Set(["_id", "_deleted", "_blocked"]);
|
|
286
|
-
function isDeletedOrBlocked(obj) {
|
|
287
|
-
return obj._deleted != null || obj._blocked != null;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// src/common/numeric/createSearchArrayMetadata.ts
|
|
291
298
|
var MATCH_MODE_BITS = {
|
|
292
299
|
start: 0,
|
|
293
300
|
end: 1,
|
|
@@ -318,7 +325,7 @@ function decodeMatchMode(encoded) {
|
|
|
318
325
|
return "start";
|
|
319
326
|
}
|
|
320
327
|
}
|
|
321
|
-
var
|
|
328
|
+
var DEFAULT_EXCLUDED_FIELDS = new Set(["_id", "_deleted", "_blocked"]);
|
|
322
329
|
function getValueByPath(obj, path) {
|
|
323
330
|
const parts = path.split(".");
|
|
324
331
|
let current = obj;
|
|
@@ -375,26 +382,29 @@ function prepareObjectForSearchNumeric(obj, spec, tokensMap) {
|
|
|
375
382
|
if (isDeletedOrBlocked(obj)) {
|
|
376
383
|
return;
|
|
377
384
|
}
|
|
378
|
-
if (spec?.extractSearchableStringFn) {
|
|
379
|
-
const searchableString = spec.extractSearchableStringFn(obj);
|
|
380
|
-
if (searchableString === undefined) {
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
return prepareStringForSearchNumeric(searchableString, tokensMap);
|
|
384
|
-
}
|
|
385
|
-
return prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap);
|
|
386
|
-
}
|
|
387
|
-
function prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap) {
|
|
388
385
|
if (spec?.enrichSearchObjectFn) {
|
|
389
386
|
spec.enrichSearchObjectFn(obj, spec.searchContext);
|
|
390
387
|
}
|
|
388
|
+
const sorted = spec?.extractSearchableStringFn ? buildSortedFromExtractFn(obj, spec.extractSearchableStringFn, tokensMap) : buildSortedFromFields(obj, spec, tokensMap);
|
|
389
|
+
if (sorted === undefined)
|
|
390
|
+
return;
|
|
391
|
+
const firstN = spec?.keyFields && spec.keyFields.length > 0 ? buildFirstNFromKeyFields(obj, spec.keyFields, spec.firstTokensN ?? DEFAULT_FIRST_TOKENS_N, tokensMap) : undefined;
|
|
392
|
+
return { sorted, firstN };
|
|
393
|
+
}
|
|
394
|
+
function buildSortedFromExtractFn(obj, extractFn, tokensMap) {
|
|
395
|
+
const str = extractFn(obj);
|
|
396
|
+
if (str === undefined)
|
|
397
|
+
return;
|
|
398
|
+
return prepareStringForSearchNumeric(str, tokensMap).sorted;
|
|
399
|
+
}
|
|
400
|
+
function buildSortedFromFields(obj, spec, tokensMap) {
|
|
391
401
|
const allTokens = [];
|
|
392
402
|
const fieldMatchModes = spec?.fieldMatchModes;
|
|
393
403
|
const fieldsToSearch = spec?.searchInFields ?? Object.keys(obj);
|
|
394
404
|
const fieldsToExclude = new Set(spec?.dontSearchInFields ?? []);
|
|
395
405
|
for (const key of fieldsToSearch) {
|
|
396
406
|
const keyStr = key;
|
|
397
|
-
if (!spec?.searchInFields &&
|
|
407
|
+
if (!spec?.searchInFields && DEFAULT_EXCLUDED_FIELDS.has(keyStr))
|
|
398
408
|
continue;
|
|
399
409
|
if (fieldsToExclude.has(key))
|
|
400
410
|
continue;
|
|
@@ -425,14 +435,42 @@ function prepareObjectFieldsForSearchNumeric(obj, spec, tokensMap) {
|
|
|
425
435
|
const uniqueTokens = [...new Set(allTokens)].sort((a, b) => a - b);
|
|
426
436
|
return new Uint32Array(uniqueTokens);
|
|
427
437
|
}
|
|
438
|
+
function buildFirstNFromKeyFields(obj, keyFields, n, tokensMap) {
|
|
439
|
+
const strings = [];
|
|
440
|
+
for (const field of keyFields) {
|
|
441
|
+
const keyStr = field;
|
|
442
|
+
const value = isDotNotation(keyStr) ? getValueByPath(obj, keyStr) : obj[field];
|
|
443
|
+
if (value == null)
|
|
444
|
+
continue;
|
|
445
|
+
extractStringsFromValue(value, strings);
|
|
446
|
+
}
|
|
447
|
+
if (strings.length === 0)
|
|
448
|
+
return;
|
|
449
|
+
const text = strings.join(" ");
|
|
450
|
+
const datesNormalized = normalizeDates(text);
|
|
451
|
+
const preprocessed = preprocessString(datesNormalized);
|
|
452
|
+
const sanitised = sanitiseString(preprocessed);
|
|
453
|
+
const stringTokens = tokenize(sanitised, DEFAULT_TOKENIZE_CONFIG);
|
|
454
|
+
if (stringTokens.length === 0)
|
|
455
|
+
return;
|
|
456
|
+
const sliced = stringTokens.slice(0, n);
|
|
457
|
+
const out = new Uint32Array(sliced.length);
|
|
458
|
+
for (let i = 0;i < sliced.length; i++) {
|
|
459
|
+
out[i] = getOrCreateTokenId(sliced[i], tokensMap);
|
|
460
|
+
}
|
|
461
|
+
return out;
|
|
462
|
+
}
|
|
428
463
|
function createSearchArrayMetadataNumeric(data, spec) {
|
|
429
464
|
const tokensMap = createTokensMap();
|
|
430
465
|
try {
|
|
431
|
-
const metadata =
|
|
466
|
+
const metadata = emptyNumericSearchMetadata();
|
|
432
467
|
for (const [id, item] of data) {
|
|
433
|
-
const
|
|
434
|
-
if (
|
|
435
|
-
metadata.set(id,
|
|
468
|
+
const result = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
469
|
+
if (result !== undefined) {
|
|
470
|
+
metadata.sorted.set(id, result.sorted);
|
|
471
|
+
if (result.firstN !== undefined) {
|
|
472
|
+
metadata.unsorted.set(id, result.firstN);
|
|
473
|
+
}
|
|
436
474
|
}
|
|
437
475
|
}
|
|
438
476
|
return metadata;
|
|
@@ -440,6 +478,9 @@ function createSearchArrayMetadataNumeric(data, spec) {
|
|
|
440
478
|
clearTokensMap(tokensMap);
|
|
441
479
|
}
|
|
442
480
|
}
|
|
481
|
+
function emptyNumericSearchMetadata() {
|
|
482
|
+
return { sorted: new Map, unsorted: new Map };
|
|
483
|
+
}
|
|
443
484
|
// src/common/numeric/createSearchLinkedMetadata.ts
|
|
444
485
|
function createSearchLinkedMetadataNumeric(primaryData, primaryMetadata, linkedData, linkedMetadata, foreignKeyGetter) {
|
|
445
486
|
const primaryToLinked = new Map;
|
|
@@ -461,14 +502,19 @@ function createSearchLinkedMetadataNumeric(primaryData, primaryMetadata, linkedD
|
|
|
461
502
|
}
|
|
462
503
|
// src/common/numeric/updateSearchMetadata.ts
|
|
463
504
|
function updateSearchMetadataNumeric(metadata, objectId, obj, spec, tokensMap) {
|
|
464
|
-
const
|
|
465
|
-
if (
|
|
466
|
-
metadata.delete(objectId);
|
|
505
|
+
const result = obj != null ? prepareObjectForSearchNumeric(obj, spec, tokensMap) : undefined;
|
|
506
|
+
if (result === undefined) {
|
|
507
|
+
metadata.sorted.delete(objectId);
|
|
508
|
+
metadata.unsorted.delete(objectId);
|
|
467
509
|
return false;
|
|
510
|
+
}
|
|
511
|
+
metadata.sorted.set(objectId, result.sorted);
|
|
512
|
+
if (result.firstN !== undefined) {
|
|
513
|
+
metadata.unsorted.set(objectId, result.firstN);
|
|
468
514
|
} else {
|
|
469
|
-
metadata.
|
|
470
|
-
return true;
|
|
515
|
+
metadata.unsorted.delete(objectId);
|
|
471
516
|
}
|
|
517
|
+
return true;
|
|
472
518
|
}
|
|
473
519
|
function updateSearchMetadataBatchNumeric(metadata, batch, spec) {
|
|
474
520
|
if (batch.length === 0) {
|
|
@@ -492,7 +538,9 @@ function updateSearchMetadataBatchNumeric(metadata, batch, spec) {
|
|
|
492
538
|
}
|
|
493
539
|
}
|
|
494
540
|
function removeFromSearchMetadataNumeric(metadata, objectId) {
|
|
495
|
-
|
|
541
|
+
const had = metadata.sorted.delete(objectId);
|
|
542
|
+
metadata.unsorted.delete(objectId);
|
|
543
|
+
return had;
|
|
496
544
|
}
|
|
497
545
|
function removeFromSearchMetadataBatchNumeric(metadata, objectIds) {
|
|
498
546
|
if (objectIds.length === 0) {
|
|
@@ -500,9 +548,10 @@ function removeFromSearchMetadataBatchNumeric(metadata, objectIds) {
|
|
|
500
548
|
}
|
|
501
549
|
let removed = 0;
|
|
502
550
|
for (const id of objectIds) {
|
|
503
|
-
|
|
551
|
+
const had = metadata.sorted.delete(id);
|
|
552
|
+
metadata.unsorted.delete(id);
|
|
553
|
+
if (had)
|
|
504
554
|
removed++;
|
|
505
|
-
}
|
|
506
555
|
}
|
|
507
556
|
return removed;
|
|
508
557
|
}
|
|
@@ -692,6 +741,106 @@ function allTokensMatchNumeric(searchTokenStrs, targetTokens, opts) {
|
|
|
692
741
|
return allPreparedTokensMatch(preparedTokens, targetTokens, opts);
|
|
693
742
|
}
|
|
694
743
|
|
|
744
|
+
// src/common/numeric/scoring.ts
|
|
745
|
+
function orderedTokenize(input) {
|
|
746
|
+
return tokenize(sanitiseString(preprocessString(normalizeDates(input))), DEFAULT_TOKENIZE_CONFIG);
|
|
747
|
+
}
|
|
748
|
+
function scoreOne(query, qTokens, itemTokens, exactKeys) {
|
|
749
|
+
if (exactKeys && exactKeys.length > 0) {
|
|
750
|
+
for (let i = 0;i < exactKeys.length; i++) {
|
|
751
|
+
if (exactKeys[i] === query)
|
|
752
|
+
return 1e5;
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
if (qTokens.length === 0)
|
|
756
|
+
return 0;
|
|
757
|
+
if (itemTokens.length === 0)
|
|
758
|
+
return 1;
|
|
759
|
+
let qi = 0;
|
|
760
|
+
const positions = [];
|
|
761
|
+
for (let i = 0;i < itemTokens.length; i++) {
|
|
762
|
+
if (qi < qTokens.length && itemTokens[i].startsWith(qTokens[qi])) {
|
|
763
|
+
positions.push(i);
|
|
764
|
+
qi++;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
if (qi === 0)
|
|
768
|
+
return 1;
|
|
769
|
+
let score = 50;
|
|
770
|
+
if (qi === qTokens.length)
|
|
771
|
+
score += 100;
|
|
772
|
+
if (positions[0] === 0)
|
|
773
|
+
score += 50;
|
|
774
|
+
let perfect = qi === qTokens.length;
|
|
775
|
+
if (perfect) {
|
|
776
|
+
for (let i = 0;i < positions.length; i++) {
|
|
777
|
+
if (positions[i] !== i) {
|
|
778
|
+
perfect = false;
|
|
779
|
+
break;
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
if (perfect)
|
|
784
|
+
score += 80;
|
|
785
|
+
if (positions.length >= 2) {
|
|
786
|
+
const span = positions[positions.length - 1] - positions[0] + 1;
|
|
787
|
+
score += positions.length / span * 30;
|
|
788
|
+
}
|
|
789
|
+
let totalLen = 0;
|
|
790
|
+
for (const t of itemTokens)
|
|
791
|
+
totalLen += t.length + 1;
|
|
792
|
+
score -= totalLen * 0.1;
|
|
793
|
+
return score;
|
|
794
|
+
}
|
|
795
|
+
function scoreBag(qTokens, itemTokens, perTokenWeight = 30) {
|
|
796
|
+
if (qTokens.length === 0 || itemTokens.length === 0)
|
|
797
|
+
return 0;
|
|
798
|
+
const usedItemIdx = new Set;
|
|
799
|
+
let score = 0;
|
|
800
|
+
for (const qt of qTokens) {
|
|
801
|
+
for (let i = 0;i < itemTokens.length; i++) {
|
|
802
|
+
if (usedItemIdx.has(i))
|
|
803
|
+
continue;
|
|
804
|
+
if (itemTokens[i].startsWith(qt)) {
|
|
805
|
+
score += perTokenWeight;
|
|
806
|
+
usedItemIdx.add(i);
|
|
807
|
+
break;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
return score;
|
|
812
|
+
}
|
|
813
|
+
function scoreOrderAndPresence(qTokens, itemTokens, weights) {
|
|
814
|
+
const orderedWeight = weights?.ordered ?? 30;
|
|
815
|
+
const presenceWeight = weights?.presence ?? 10;
|
|
816
|
+
if (qTokens.length === 0 || itemTokens.length === 0)
|
|
817
|
+
return 0;
|
|
818
|
+
const matchedQueryIndices = new Set;
|
|
819
|
+
let qi = 0;
|
|
820
|
+
let score = 0;
|
|
821
|
+
for (let i = 0;i < itemTokens.length && qi < qTokens.length; i++) {
|
|
822
|
+
if (itemTokens[i].startsWith(qTokens[qi])) {
|
|
823
|
+
score += orderedWeight;
|
|
824
|
+
matchedQueryIndices.add(qi);
|
|
825
|
+
qi++;
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
if (matchedQueryIndices.size < qTokens.length) {
|
|
829
|
+
for (let qj = 0;qj < qTokens.length; qj++) {
|
|
830
|
+
if (matchedQueryIndices.has(qj))
|
|
831
|
+
continue;
|
|
832
|
+
const qt = qTokens[qj];
|
|
833
|
+
for (let i = 0;i < itemTokens.length; i++) {
|
|
834
|
+
if (itemTokens[i].startsWith(qt)) {
|
|
835
|
+
score += presenceWeight;
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
return score;
|
|
842
|
+
}
|
|
843
|
+
|
|
695
844
|
// src/common/numeric/searchInData.ts
|
|
696
845
|
function searchInDataReturnIdsNumeric(query, metadata, opts) {
|
|
697
846
|
return searchInDataReturnIdsWithLimitNumeric(query, metadata, Infinity, opts);
|
|
@@ -709,20 +858,48 @@ function searchInDataReturnObjectsNumeric(query, metadata, data, opts) {
|
|
|
709
858
|
}
|
|
710
859
|
function searchInDataReturnIdsWithLimitNumeric(query, metadata, limit, opts) {
|
|
711
860
|
const queryTokenStrs = prepareStringForSearch(query);
|
|
712
|
-
if (queryTokenStrs.length === 0)
|
|
861
|
+
if (queryTokenStrs.length === 0)
|
|
713
862
|
return [];
|
|
714
|
-
}
|
|
715
863
|
const preparedTokens = prepareQueryTokens(queryTokenStrs);
|
|
716
|
-
const
|
|
717
|
-
for (const [id, targetTokens] of metadata) {
|
|
864
|
+
const candidates = [];
|
|
865
|
+
for (const [id, targetTokens] of metadata.sorted) {
|
|
718
866
|
if (allPreparedTokensMatch(preparedTokens, targetTokens, opts)) {
|
|
719
|
-
|
|
720
|
-
if (results.length >= limit) {
|
|
721
|
-
break;
|
|
722
|
-
}
|
|
867
|
+
candidates.push(id);
|
|
723
868
|
}
|
|
724
869
|
}
|
|
725
|
-
|
|
870
|
+
if (candidates.length === 0)
|
|
871
|
+
return [];
|
|
872
|
+
const qTokens = orderedTokenize(query);
|
|
873
|
+
const hasUnsorted = metadata.unsorted.size > 0;
|
|
874
|
+
if (!hasUnsorted) {
|
|
875
|
+
if (limit === Infinity || limit >= candidates.length)
|
|
876
|
+
return candidates;
|
|
877
|
+
return candidates.slice(0, limit);
|
|
878
|
+
}
|
|
879
|
+
const scored = new Array(candidates.length);
|
|
880
|
+
for (let i = 0;i < candidates.length; i++) {
|
|
881
|
+
const id = candidates[i];
|
|
882
|
+
const unsortedIds = metadata.unsorted.get(id);
|
|
883
|
+
if (unsortedIds === undefined) {
|
|
884
|
+
scored[i] = { id, score: 0, order: i };
|
|
885
|
+
continue;
|
|
886
|
+
}
|
|
887
|
+
const itemTokens = new Array(unsortedIds.length);
|
|
888
|
+
for (let j = 0;j < unsortedIds.length; j++) {
|
|
889
|
+
itemTokens[j] = tokens[unsortedIds[j]] ?? "";
|
|
890
|
+
}
|
|
891
|
+
scored[i] = { id, score: scoreOne(query, qTokens, itemTokens), order: i };
|
|
892
|
+
}
|
|
893
|
+
scored.sort((a, b) => {
|
|
894
|
+
if (a.score !== b.score)
|
|
895
|
+
return b.score - a.score;
|
|
896
|
+
return a.order - b.order;
|
|
897
|
+
});
|
|
898
|
+
const out = [];
|
|
899
|
+
const max = limit === Infinity ? scored.length : Math.min(limit, scored.length);
|
|
900
|
+
for (let i = 0;i < max; i++)
|
|
901
|
+
out.push(scored[i].id);
|
|
902
|
+
return out;
|
|
726
903
|
}
|
|
727
904
|
// src/common/numeric/findInLinkedArrays.ts
|
|
728
905
|
function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
@@ -733,11 +910,10 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
|
733
910
|
const preparedTokens = prepareQueryTokens(queryTokenStrs);
|
|
734
911
|
const positiveTokens = preparedTokens.filter((t) => !t.negated);
|
|
735
912
|
const negatedTokens = preparedTokens.filter((t) => t.negated);
|
|
736
|
-
const
|
|
913
|
+
const scored = [];
|
|
914
|
+
let orderCounter = 0;
|
|
737
915
|
for (const [primaryId, primary] of linked.primaryData) {
|
|
738
|
-
|
|
739
|
-
break;
|
|
740
|
-
const primaryTokens = linked.primaryMeta.get(primaryId);
|
|
916
|
+
const primaryTokens = linked.primaryMeta.sorted.get(primaryId);
|
|
741
917
|
if (!primaryTokens)
|
|
742
918
|
continue;
|
|
743
919
|
const linkedIds = linked.primaryToLinked.get(primaryId) || [];
|
|
@@ -748,22 +924,20 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
|
748
924
|
break;
|
|
749
925
|
}
|
|
750
926
|
}
|
|
751
|
-
if (negatedMatchesInPrimary)
|
|
927
|
+
if (negatedMatchesInPrimary)
|
|
752
928
|
continue;
|
|
753
|
-
}
|
|
754
929
|
let totalLength = primaryTokens.length;
|
|
755
930
|
for (const linkedId of linkedIds) {
|
|
756
|
-
const linkedTokens = linked.linkedMeta.get(linkedId);
|
|
757
|
-
if (linkedTokens)
|
|
931
|
+
const linkedTokens = linked.linkedMeta.sorted.get(linkedId);
|
|
932
|
+
if (linkedTokens)
|
|
758
933
|
totalLength += linkedTokens.length;
|
|
759
|
-
}
|
|
760
934
|
}
|
|
761
935
|
const allTokens = new Uint32Array(totalLength);
|
|
762
936
|
let offset = 0;
|
|
763
937
|
allTokens.set(primaryTokens, offset);
|
|
764
938
|
offset += primaryTokens.length;
|
|
765
939
|
for (const linkedId of linkedIds) {
|
|
766
|
-
const linkedTokens = linked.linkedMeta.get(linkedId);
|
|
940
|
+
const linkedTokens = linked.linkedMeta.sorted.get(linkedId);
|
|
767
941
|
if (linkedTokens) {
|
|
768
942
|
allTokens.set(linkedTokens, offset);
|
|
769
943
|
offset += linkedTokens.length;
|
|
@@ -777,230 +951,289 @@ function findInLinkedArraysNumeric(query, linked, limit = 10, opts) {
|
|
|
777
951
|
break;
|
|
778
952
|
}
|
|
779
953
|
}
|
|
780
|
-
if (allPositiveMatch)
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
954
|
+
if (!allPositiveMatch)
|
|
955
|
+
continue;
|
|
956
|
+
let anyMatchInPrimary = false;
|
|
957
|
+
let anyMatchInLinked = false;
|
|
958
|
+
const matchingLinkedIds = new Set;
|
|
959
|
+
const tokensMatchingPrimary = new Set;
|
|
960
|
+
for (const preparedToken of positiveTokens) {
|
|
961
|
+
if (matchPreparedTokenInSortedList(preparedToken, primaryTokens, opts)) {
|
|
962
|
+
anyMatchInPrimary = true;
|
|
963
|
+
tokensMatchingPrimary.add(preparedToken);
|
|
790
964
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
if (matchesNegatedToken) {
|
|
804
|
-
continue;
|
|
805
|
-
}
|
|
806
|
-
if (tokensForLinkedMatching.length > 0) {
|
|
807
|
-
const matchesAllNonPrimaryTokens = tokensForLinkedMatching.every((preparedToken) => matchPreparedTokenInSortedList(preparedToken, linkedTokens, opts));
|
|
808
|
-
if (matchesAllNonPrimaryTokens) {
|
|
809
|
-
anyMatchInLinked = true;
|
|
810
|
-
matchingLinkedIds.add(linkedId);
|
|
811
|
-
}
|
|
812
|
-
} else {
|
|
813
|
-
matchingLinkedIds.add(linkedId);
|
|
814
|
-
}
|
|
965
|
+
}
|
|
966
|
+
const tokensForLinkedMatching = positiveTokens.filter((t) => !tokensMatchingPrimary.has(t));
|
|
967
|
+
if (tokensForLinkedMatching.length > 0 || negatedTokens.length > 0) {
|
|
968
|
+
for (const linkedId of linkedIds) {
|
|
969
|
+
const linkedTokens = linked.linkedMeta.sorted.get(linkedId);
|
|
970
|
+
if (!linkedTokens)
|
|
971
|
+
continue;
|
|
972
|
+
let matchesNegatedToken = false;
|
|
973
|
+
for (const negatedToken of negatedTokens) {
|
|
974
|
+
if (matchPreparedTokenInSortedList(negatedToken, linkedTokens, opts)) {
|
|
975
|
+
matchesNegatedToken = true;
|
|
976
|
+
break;
|
|
815
977
|
}
|
|
816
978
|
}
|
|
979
|
+
if (matchesNegatedToken)
|
|
980
|
+
continue;
|
|
981
|
+
if (tokensForLinkedMatching.length > 0) {
|
|
982
|
+
const matchesAllNonPrimaryTokens = tokensForLinkedMatching.every((preparedToken) => matchPreparedTokenInSortedList(preparedToken, linkedTokens, opts));
|
|
983
|
+
if (matchesAllNonPrimaryTokens) {
|
|
984
|
+
anyMatchInLinked = true;
|
|
985
|
+
matchingLinkedIds.add(linkedId);
|
|
986
|
+
}
|
|
987
|
+
} else {
|
|
988
|
+
matchingLinkedIds.add(linkedId);
|
|
989
|
+
}
|
|
817
990
|
}
|
|
818
|
-
|
|
991
|
+
}
|
|
992
|
+
if (tokensForLinkedMatching.length > 0 && matchingLinkedIds.size === 0) {
|
|
993
|
+
continue;
|
|
994
|
+
}
|
|
995
|
+
const matchedLinked = Array.from(matchingLinkedIds).map((id) => linked.linkedData.get(id)).filter((item) => item !== undefined);
|
|
996
|
+
const result = {
|
|
997
|
+
primary,
|
|
998
|
+
linked: matchedLinked,
|
|
999
|
+
matchedIn: anyMatchInPrimary && anyMatchInLinked ? "both" : anyMatchInPrimary ? "primary" : "linked"
|
|
1000
|
+
};
|
|
1001
|
+
scored.push({
|
|
1002
|
+
result,
|
|
1003
|
+
score: 0,
|
|
1004
|
+
order: orderCounter++,
|
|
1005
|
+
primaryId,
|
|
1006
|
+
matchedLinkedIds: Array.from(matchingLinkedIds)
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
if (scored.length === 0) {
|
|
1010
|
+
return { queryTokens: queryTokenStrs, results: [], hasNegation: negatedTokens.length > 0 };
|
|
1011
|
+
}
|
|
1012
|
+
const qTokens = orderedTokenize(query);
|
|
1013
|
+
const hasUnsorted = linked.primaryMeta.unsorted.size > 0 || linked.linkedMeta.unsorted.size > 0;
|
|
1014
|
+
if (hasUnsorted) {
|
|
1015
|
+
for (const s of scored) {
|
|
1016
|
+
const itemTokenIds = [];
|
|
1017
|
+
const pu = linked.primaryMeta.unsorted.get(s.primaryId);
|
|
1018
|
+
if (pu)
|
|
1019
|
+
for (const tid of pu)
|
|
1020
|
+
itemTokenIds.push(tid);
|
|
1021
|
+
for (const lid of s.matchedLinkedIds) {
|
|
1022
|
+
const lu = linked.linkedMeta.unsorted.get(lid);
|
|
1023
|
+
if (lu)
|
|
1024
|
+
for (const tid of lu)
|
|
1025
|
+
itemTokenIds.push(tid);
|
|
1026
|
+
}
|
|
1027
|
+
if (itemTokenIds.length === 0) {
|
|
1028
|
+
s.score = 0;
|
|
819
1029
|
continue;
|
|
820
1030
|
}
|
|
821
|
-
const
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
});
|
|
1031
|
+
const itemTokens = new Array(itemTokenIds.length);
|
|
1032
|
+
for (let i = 0;i < itemTokenIds.length; i++) {
|
|
1033
|
+
itemTokens[i] = tokens[itemTokenIds[i]] ?? "";
|
|
1034
|
+
}
|
|
1035
|
+
s.score = scoreOne(query, qTokens, itemTokens);
|
|
827
1036
|
}
|
|
828
1037
|
}
|
|
1038
|
+
scored.sort((a, b) => {
|
|
1039
|
+
if (a.score !== b.score)
|
|
1040
|
+
return b.score - a.score;
|
|
1041
|
+
return a.order - b.order;
|
|
1042
|
+
});
|
|
1043
|
+
const max = Math.min(limit, scored.length);
|
|
1044
|
+
const results = new Array(max);
|
|
1045
|
+
for (let i = 0;i < max; i++)
|
|
1046
|
+
results[i] = scored[i].result;
|
|
829
1047
|
return { queryTokens: queryTokenStrs, results, hasNegation: negatedTokens.length > 0 };
|
|
830
1048
|
}
|
|
831
1049
|
function findInLinkedArraysSimpleNumeric(query, linked, limit = 10, opts) {
|
|
832
1050
|
return findInLinkedArraysNumeric(query, linked, limit, opts).results;
|
|
833
1051
|
}
|
|
834
1052
|
// src/common/numeric/AugmentedMetadata.ts
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
if (
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
if (tokens2 && tokens2.length > 0) {
|
|
855
|
-
this.augmentedTokens.set(id, tokens2);
|
|
1053
|
+
function mergeSortedTokenArrays(a, b) {
|
|
1054
|
+
const merged = new Uint32Array(a.length + b.length);
|
|
1055
|
+
let i = 0, j = 0, k = 0;
|
|
1056
|
+
let lastToken = -1;
|
|
1057
|
+
while (i < a.length && j < b.length) {
|
|
1058
|
+
const tokenA = a[i];
|
|
1059
|
+
const tokenB = b[j];
|
|
1060
|
+
if (tokenA < tokenB) {
|
|
1061
|
+
if (tokenA !== lastToken) {
|
|
1062
|
+
merged[k++] = tokenA;
|
|
1063
|
+
lastToken = tokenA;
|
|
1064
|
+
}
|
|
1065
|
+
i++;
|
|
1066
|
+
} else if (tokenA > tokenB) {
|
|
1067
|
+
if (tokenB !== lastToken) {
|
|
1068
|
+
merged[k++] = tokenB;
|
|
1069
|
+
lastToken = tokenB;
|
|
1070
|
+
}
|
|
1071
|
+
j++;
|
|
856
1072
|
} else {
|
|
857
|
-
|
|
1073
|
+
if (tokenA !== lastToken) {
|
|
1074
|
+
merged[k++] = tokenA;
|
|
1075
|
+
lastToken = tokenA;
|
|
1076
|
+
}
|
|
1077
|
+
i++;
|
|
1078
|
+
j++;
|
|
858
1079
|
}
|
|
859
|
-
clearTokensMap(tokensMap);
|
|
860
1080
|
}
|
|
861
|
-
|
|
862
|
-
const
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
continue;
|
|
867
|
-
}
|
|
868
|
-
const tokens2 = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
869
|
-
if (tokens2 && tokens2.length > 0) {
|
|
870
|
-
this.augmentedTokens.set(id, tokens2);
|
|
871
|
-
} else {
|
|
872
|
-
this.augmentedTokens.delete(id);
|
|
873
|
-
}
|
|
1081
|
+
while (i < a.length) {
|
|
1082
|
+
const tokenA = a[i];
|
|
1083
|
+
if (tokenA !== lastToken) {
|
|
1084
|
+
merged[k++] = tokenA;
|
|
1085
|
+
lastToken = tokenA;
|
|
874
1086
|
}
|
|
875
|
-
|
|
1087
|
+
i++;
|
|
876
1088
|
}
|
|
877
|
-
|
|
878
|
-
|
|
1089
|
+
while (j < b.length) {
|
|
1090
|
+
const tokenB = b[j];
|
|
1091
|
+
if (tokenB !== lastToken) {
|
|
1092
|
+
merged[k++] = tokenB;
|
|
1093
|
+
lastToken = tokenB;
|
|
1094
|
+
}
|
|
1095
|
+
j++;
|
|
879
1096
|
}
|
|
880
|
-
|
|
881
|
-
|
|
1097
|
+
return merged.slice(0, k);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
class AugmentedSortedMap extends Map {
|
|
1101
|
+
base;
|
|
1102
|
+
augTokens;
|
|
1103
|
+
constructor(base, augTokens) {
|
|
1104
|
+
super();
|
|
1105
|
+
this.base = base;
|
|
1106
|
+
this.augTokens = augTokens;
|
|
882
1107
|
}
|
|
883
1108
|
get(id) {
|
|
884
|
-
const baseTokens = this.
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
if (
|
|
1109
|
+
const baseTokens = this.base.get(id);
|
|
1110
|
+
const augTokens = this.augTokens.get(id);
|
|
1111
|
+
if (baseTokens === undefined)
|
|
1112
|
+
return augTokens;
|
|
1113
|
+
if (augTokens === undefined)
|
|
889
1114
|
return baseTokens;
|
|
890
|
-
return
|
|
1115
|
+
return mergeSortedTokenArrays(baseTokens, augTokens);
|
|
891
1116
|
}
|
|
892
1117
|
has(id) {
|
|
893
|
-
return this.
|
|
1118
|
+
return this.base.has(id) || this.augTokens.has(id);
|
|
894
1119
|
}
|
|
895
1120
|
get size() {
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
const
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
if (baseResult.done) {
|
|
905
|
-
return { done: true, value: undefined };
|
|
906
|
-
}
|
|
907
|
-
const [id, baseTokens] = baseResult.value;
|
|
908
|
-
const augTokens = self.augmentedTokens.get(id);
|
|
909
|
-
const tokens2 = augTokens ? self.mergeSortedTokenArrays(baseTokens, augTokens) : baseTokens;
|
|
910
|
-
return { done: false, value: [id, tokens2] };
|
|
911
|
-
},
|
|
912
|
-
[Symbol.iterator]() {
|
|
913
|
-
return this;
|
|
914
|
-
},
|
|
915
|
-
[Symbol.dispose]() {}
|
|
916
|
-
};
|
|
1121
|
+
if (this.augTokens.size === 0)
|
|
1122
|
+
return this.base.size;
|
|
1123
|
+
let count = this.base.size;
|
|
1124
|
+
for (const id of this.augTokens.keys()) {
|
|
1125
|
+
if (!this.base.has(id))
|
|
1126
|
+
count++;
|
|
1127
|
+
}
|
|
1128
|
+
return count;
|
|
917
1129
|
}
|
|
918
1130
|
keys() {
|
|
919
|
-
return this.
|
|
1131
|
+
return this.unionIdIterator();
|
|
920
1132
|
}
|
|
921
1133
|
values() {
|
|
922
1134
|
const self = this;
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
return tokens2 ? { done: false, value: tokens2 } : { done: true, value: undefined };
|
|
932
|
-
},
|
|
933
|
-
[Symbol.iterator]() {
|
|
934
|
-
return this;
|
|
935
|
-
},
|
|
936
|
-
[Symbol.dispose]() {}
|
|
937
|
-
};
|
|
1135
|
+
function* gen() {
|
|
1136
|
+
for (const id of self.unionIdIterator()) {
|
|
1137
|
+
const tokens2 = self.get(id);
|
|
1138
|
+
if (tokens2 !== undefined)
|
|
1139
|
+
yield tokens2;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
return gen();
|
|
938
1143
|
}
|
|
939
1144
|
entries() {
|
|
940
|
-
|
|
1145
|
+
const self = this;
|
|
1146
|
+
function* gen() {
|
|
1147
|
+
for (const id of self.unionIdIterator()) {
|
|
1148
|
+
const tokens2 = self.get(id);
|
|
1149
|
+
if (tokens2 !== undefined)
|
|
1150
|
+
yield [id, tokens2];
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
return gen();
|
|
1154
|
+
}
|
|
1155
|
+
[Symbol.iterator]() {
|
|
1156
|
+
return this.entries();
|
|
941
1157
|
}
|
|
942
1158
|
forEach(callbackfn) {
|
|
943
|
-
for (const [id, tokens2] of this) {
|
|
1159
|
+
for (const [id, tokens2] of this.entries()) {
|
|
944
1160
|
callbackfn(tokens2, id, this);
|
|
945
1161
|
}
|
|
946
1162
|
}
|
|
947
1163
|
set(_key, _value) {
|
|
948
|
-
throw new Error("AugmentedMetadata.
|
|
1164
|
+
throw new Error("AugmentedMetadata.sorted is read-only. Use updateAugmented() instead.");
|
|
949
1165
|
}
|
|
950
1166
|
delete(_key) {
|
|
951
|
-
throw new Error("AugmentedMetadata.
|
|
1167
|
+
throw new Error("AugmentedMetadata.sorted is read-only. Use clearAugmented() instead.");
|
|
952
1168
|
}
|
|
953
1169
|
clear() {
|
|
954
|
-
throw new Error("AugmentedMetadata.
|
|
1170
|
+
throw new Error("AugmentedMetadata.sorted is read-only. Use clearAllAugmented() instead.");
|
|
955
1171
|
}
|
|
956
1172
|
get [Symbol.toStringTag]() {
|
|
957
|
-
return "
|
|
958
|
-
}
|
|
959
|
-
|
|
960
|
-
const
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
const tokenA = a[i];
|
|
965
|
-
const tokenB = b[j];
|
|
966
|
-
if (tokenA < tokenB) {
|
|
967
|
-
if (tokenA !== lastToken) {
|
|
968
|
-
merged[k++] = tokenA;
|
|
969
|
-
lastToken = tokenA;
|
|
970
|
-
}
|
|
971
|
-
i++;
|
|
972
|
-
} else if (tokenA > tokenB) {
|
|
973
|
-
if (tokenB !== lastToken) {
|
|
974
|
-
merged[k++] = tokenB;
|
|
975
|
-
lastToken = tokenB;
|
|
976
|
-
}
|
|
977
|
-
j++;
|
|
978
|
-
} else {
|
|
979
|
-
if (tokenA !== lastToken) {
|
|
980
|
-
merged[k++] = tokenA;
|
|
981
|
-
lastToken = tokenA;
|
|
982
|
-
}
|
|
983
|
-
i++;
|
|
984
|
-
j++;
|
|
985
|
-
}
|
|
1173
|
+
return "AugmentedSortedMap";
|
|
1174
|
+
}
|
|
1175
|
+
*unionIdIterator() {
|
|
1176
|
+
const seen = new Set;
|
|
1177
|
+
for (const id of this.base.keys()) {
|
|
1178
|
+
seen.add(id);
|
|
1179
|
+
yield id;
|
|
986
1180
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
merged[k++] = tokenA;
|
|
991
|
-
lastToken = tokenA;
|
|
992
|
-
}
|
|
993
|
-
i++;
|
|
1181
|
+
for (const id of this.augTokens.keys()) {
|
|
1182
|
+
if (!seen.has(id))
|
|
1183
|
+
yield id;
|
|
994
1184
|
}
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
class AugmentedMetadata {
|
|
1189
|
+
sorted;
|
|
1190
|
+
unsorted;
|
|
1191
|
+
augmentedTokens;
|
|
1192
|
+
spec;
|
|
1193
|
+
constructor(baseMetadata, spec, augmentedDataMap) {
|
|
1194
|
+
this.augmentedTokens = new Map;
|
|
1195
|
+
this.spec = spec;
|
|
1196
|
+
this.sorted = new AugmentedSortedMap(baseMetadata.sorted, this.augmentedTokens);
|
|
1197
|
+
this.unsorted = baseMetadata.unsorted;
|
|
1198
|
+
if (augmentedDataMap && augmentedDataMap.size > 0) {
|
|
1199
|
+
this.updateAugmentedBatch(augmentedDataMap);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
updateAugmented(id, augmentedData) {
|
|
1203
|
+
if (augmentedData == null) {
|
|
1204
|
+
this.augmentedTokens.delete(id);
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
const tokensMap = createTokensMap();
|
|
1208
|
+
const prepared = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
1209
|
+
clearTokensMap(tokensMap);
|
|
1210
|
+
if (prepared !== undefined && prepared.sorted.length > 0) {
|
|
1211
|
+
this.augmentedTokens.set(id, prepared.sorted);
|
|
1212
|
+
} else {
|
|
1213
|
+
this.augmentedTokens.delete(id);
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
updateAugmentedBatch(augmentedDataMap) {
|
|
1217
|
+
const tokensMap = createTokensMap();
|
|
1218
|
+
for (const [id, augmentedData] of augmentedDataMap) {
|
|
1219
|
+
if (augmentedData == null) {
|
|
1220
|
+
this.augmentedTokens.delete(id);
|
|
1221
|
+
continue;
|
|
1222
|
+
}
|
|
1223
|
+
const prepared = prepareObjectForSearchNumeric(augmentedData, this.spec, tokensMap);
|
|
1224
|
+
if (prepared !== undefined && prepared.sorted.length > 0) {
|
|
1225
|
+
this.augmentedTokens.set(id, prepared.sorted);
|
|
1226
|
+
} else {
|
|
1227
|
+
this.augmentedTokens.delete(id);
|
|
1000
1228
|
}
|
|
1001
|
-
j++;
|
|
1002
1229
|
}
|
|
1003
|
-
|
|
1230
|
+
clearTokensMap(tokensMap);
|
|
1231
|
+
}
|
|
1232
|
+
clearAugmented(id) {
|
|
1233
|
+
this.augmentedTokens.delete(id);
|
|
1234
|
+
}
|
|
1235
|
+
clearAllAugmented() {
|
|
1236
|
+
this.augmentedTokens.clear();
|
|
1004
1237
|
}
|
|
1005
1238
|
}
|
|
1006
1239
|
// src/common/numeric/syncSearchArrayMetadata.ts
|
|
@@ -1013,6 +1246,25 @@ function tokensEqual(a, b) {
|
|
|
1013
1246
|
}
|
|
1014
1247
|
return true;
|
|
1015
1248
|
}
|
|
1249
|
+
function firstNEqual(a, b) {
|
|
1250
|
+
if (a === undefined && b === undefined)
|
|
1251
|
+
return true;
|
|
1252
|
+
if (a === undefined || b === undefined)
|
|
1253
|
+
return false;
|
|
1254
|
+
return tokensEqual(a, b);
|
|
1255
|
+
}
|
|
1256
|
+
function applyPreparedTokens(metadata, id, result) {
|
|
1257
|
+
metadata.sorted.set(id, result.sorted);
|
|
1258
|
+
if (result.firstN !== undefined) {
|
|
1259
|
+
metadata.unsorted.set(id, result.firstN);
|
|
1260
|
+
} else {
|
|
1261
|
+
metadata.unsorted.delete(id);
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
function deletePreparedTokens(metadata, id) {
|
|
1265
|
+
metadata.sorted.delete(id);
|
|
1266
|
+
metadata.unsorted.delete(id);
|
|
1267
|
+
}
|
|
1016
1268
|
function syncSearchArrayMetadataNumeric(metadata, newData, spec) {
|
|
1017
1269
|
const result = {
|
|
1018
1270
|
added: 0,
|
|
@@ -1023,30 +1275,31 @@ function syncSearchArrayMetadataNumeric(metadata, newData, spec) {
|
|
|
1023
1275
|
removedIds: []
|
|
1024
1276
|
};
|
|
1025
1277
|
const tokensMap = createTokensMap();
|
|
1026
|
-
for (const id of metadata.keys()) {
|
|
1278
|
+
for (const id of metadata.sorted.keys()) {
|
|
1027
1279
|
if (!newData.has(id)) {
|
|
1028
|
-
metadata
|
|
1280
|
+
deletePreparedTokens(metadata, id);
|
|
1029
1281
|
result.removed++;
|
|
1030
1282
|
result.removedIds.push(id);
|
|
1031
1283
|
}
|
|
1032
1284
|
}
|
|
1033
1285
|
for (const [id, item] of newData) {
|
|
1034
|
-
const
|
|
1035
|
-
if (
|
|
1036
|
-
if (metadata.has(id)) {
|
|
1037
|
-
metadata
|
|
1286
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1287
|
+
if (prepared === undefined) {
|
|
1288
|
+
if (metadata.sorted.has(id)) {
|
|
1289
|
+
deletePreparedTokens(metadata, id);
|
|
1038
1290
|
result.removed++;
|
|
1039
1291
|
result.removedIds.push(id);
|
|
1040
1292
|
}
|
|
1041
1293
|
continue;
|
|
1042
1294
|
}
|
|
1043
|
-
const
|
|
1044
|
-
|
|
1045
|
-
|
|
1295
|
+
const existingSorted = metadata.sorted.get(id);
|
|
1296
|
+
const existingFirstN = metadata.unsorted.get(id);
|
|
1297
|
+
if (existingSorted === undefined) {
|
|
1298
|
+
applyPreparedTokens(metadata, id, prepared);
|
|
1046
1299
|
result.added++;
|
|
1047
1300
|
result.addedIds.push(id);
|
|
1048
|
-
} else if (!tokensEqual(
|
|
1049
|
-
metadata
|
|
1301
|
+
} else if (!tokensEqual(existingSorted, prepared.sorted) || !firstNEqual(existingFirstN, prepared.firstN)) {
|
|
1302
|
+
applyPreparedTokens(metadata, id, prepared);
|
|
1050
1303
|
result.updated++;
|
|
1051
1304
|
result.updatedIds.push(id);
|
|
1052
1305
|
}
|
|
@@ -1066,7 +1319,7 @@ function syncSearchArrayMetadataNumericWithPrevious(metadata, previousData, newD
|
|
|
1066
1319
|
const tokensMap = createTokensMap();
|
|
1067
1320
|
for (const id of previousData.keys()) {
|
|
1068
1321
|
if (!newData.has(id)) {
|
|
1069
|
-
metadata
|
|
1322
|
+
deletePreparedTokens(metadata, id);
|
|
1070
1323
|
result.removed++;
|
|
1071
1324
|
result.removedIds.push(id);
|
|
1072
1325
|
}
|
|
@@ -1074,22 +1327,23 @@ function syncSearchArrayMetadataNumericWithPrevious(metadata, previousData, newD
|
|
|
1074
1327
|
for (const [id, item] of newData) {
|
|
1075
1328
|
const wasInPrevious = previousData.has(id);
|
|
1076
1329
|
if (!wasInPrevious) {
|
|
1077
|
-
const
|
|
1078
|
-
if (
|
|
1079
|
-
metadata
|
|
1330
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1331
|
+
if (prepared !== undefined) {
|
|
1332
|
+
applyPreparedTokens(metadata, id, prepared);
|
|
1080
1333
|
result.added++;
|
|
1081
1334
|
result.addedIds.push(id);
|
|
1082
1335
|
}
|
|
1083
1336
|
} else if (!options?.skipUpdateCheck) {
|
|
1084
|
-
const
|
|
1085
|
-
if (
|
|
1086
|
-
metadata
|
|
1337
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1338
|
+
if (prepared === undefined) {
|
|
1339
|
+
deletePreparedTokens(metadata, id);
|
|
1087
1340
|
result.removed++;
|
|
1088
1341
|
result.removedIds.push(id);
|
|
1089
1342
|
} else {
|
|
1090
|
-
const
|
|
1091
|
-
|
|
1092
|
-
|
|
1343
|
+
const existingSorted = metadata.sorted.get(id);
|
|
1344
|
+
const existingFirstN = metadata.unsorted.get(id);
|
|
1345
|
+
if (existingSorted && (!tokensEqual(existingSorted, prepared.sorted) || !firstNEqual(existingFirstN, prepared.firstN))) {
|
|
1346
|
+
applyPreparedTokens(metadata, id, prepared);
|
|
1093
1347
|
result.updated++;
|
|
1094
1348
|
result.updatedIds.push(id);
|
|
1095
1349
|
}
|
|
@@ -1109,29 +1363,48 @@ function tokensEqual2(a, b) {
|
|
|
1109
1363
|
}
|
|
1110
1364
|
return true;
|
|
1111
1365
|
}
|
|
1366
|
+
function firstNEqual2(a, b) {
|
|
1367
|
+
if (a === undefined && b === undefined)
|
|
1368
|
+
return true;
|
|
1369
|
+
if (a === undefined || b === undefined)
|
|
1370
|
+
return false;
|
|
1371
|
+
return tokensEqual2(a, b);
|
|
1372
|
+
}
|
|
1373
|
+
function applyOrClear(meta, id, prepared) {
|
|
1374
|
+
if (prepared === undefined) {
|
|
1375
|
+
meta.sorted.delete(id);
|
|
1376
|
+
meta.unsorted.delete(id);
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
meta.sorted.set(id, prepared.sorted);
|
|
1380
|
+
if (prepared.firstN !== undefined) {
|
|
1381
|
+
meta.unsorted.set(id, prepared.firstN);
|
|
1382
|
+
} else {
|
|
1383
|
+
meta.unsorted.delete(id);
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
function clearTokens(meta, id) {
|
|
1387
|
+
meta.sorted.delete(id);
|
|
1388
|
+
meta.unsorted.delete(id);
|
|
1389
|
+
}
|
|
1112
1390
|
function upsertPrimaryItemNumeric(linked, item, spec) {
|
|
1113
1391
|
const id = item._id;
|
|
1114
1392
|
const wasAdded = !linked.primaryData.has(id);
|
|
1115
1393
|
linked.primaryData.set(id, item);
|
|
1116
1394
|
const tokensMap = createTokensMap();
|
|
1117
|
-
const
|
|
1395
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1118
1396
|
clearTokensMap(tokensMap);
|
|
1119
|
-
|
|
1120
|
-
linked.primaryMeta.set(id, tokens2);
|
|
1121
|
-
} else {
|
|
1122
|
-
linked.primaryMeta.delete(id);
|
|
1123
|
-
}
|
|
1397
|
+
applyOrClear(linked.primaryMeta, id, prepared);
|
|
1124
1398
|
if (wasAdded && !linked.primaryToLinked.has(id)) {
|
|
1125
1399
|
linked.primaryToLinked.set(id, []);
|
|
1126
1400
|
}
|
|
1127
1401
|
return { added: wasAdded };
|
|
1128
1402
|
}
|
|
1129
1403
|
function removePrimaryItemNumeric(linked, primaryId) {
|
|
1130
|
-
if (!linked.primaryData.has(primaryId))
|
|
1404
|
+
if (!linked.primaryData.has(primaryId))
|
|
1131
1405
|
return false;
|
|
1132
|
-
}
|
|
1133
1406
|
linked.primaryData.delete(primaryId);
|
|
1134
|
-
linked.primaryMeta
|
|
1407
|
+
clearTokens(linked.primaryMeta, primaryId);
|
|
1135
1408
|
linked.primaryToLinked.delete(primaryId);
|
|
1136
1409
|
return true;
|
|
1137
1410
|
}
|
|
@@ -1140,35 +1413,28 @@ function upsertLinkedItemNumeric(linked, item, foreignKeyGetter, spec) {
|
|
|
1140
1413
|
const newPrimaryId = foreignKeyGetter(item);
|
|
1141
1414
|
let previousPrimaryId;
|
|
1142
1415
|
const existingItem = linked.linkedData.get(id);
|
|
1143
|
-
if (existingItem)
|
|
1416
|
+
if (existingItem)
|
|
1144
1417
|
previousPrimaryId = foreignKeyGetter(existingItem);
|
|
1145
|
-
}
|
|
1146
1418
|
const wasAdded = !existingItem;
|
|
1147
1419
|
linked.linkedData.set(id, item);
|
|
1148
1420
|
const tokensMap = createTokensMap();
|
|
1149
|
-
const
|
|
1421
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1150
1422
|
clearTokensMap(tokensMap);
|
|
1151
|
-
|
|
1152
|
-
linked.linkedMeta.set(id, tokens2);
|
|
1153
|
-
} else {
|
|
1154
|
-
linked.linkedMeta.delete(id);
|
|
1155
|
-
}
|
|
1423
|
+
applyOrClear(linked.linkedMeta, id, prepared);
|
|
1156
1424
|
if (previousPrimaryId !== newPrimaryId) {
|
|
1157
1425
|
if (previousPrimaryId) {
|
|
1158
1426
|
const oldList = linked.primaryToLinked.get(previousPrimaryId);
|
|
1159
1427
|
if (oldList) {
|
|
1160
1428
|
const index = oldList.indexOf(id);
|
|
1161
|
-
if (index !== -1)
|
|
1429
|
+
if (index !== -1)
|
|
1162
1430
|
oldList.splice(index, 1);
|
|
1163
|
-
}
|
|
1164
1431
|
}
|
|
1165
1432
|
}
|
|
1166
1433
|
if (newPrimaryId) {
|
|
1167
1434
|
const newList = linked.primaryToLinked.get(newPrimaryId);
|
|
1168
1435
|
if (newList) {
|
|
1169
|
-
if (!newList.includes(id))
|
|
1436
|
+
if (!newList.includes(id))
|
|
1170
1437
|
newList.push(id);
|
|
1171
|
-
}
|
|
1172
1438
|
} else {
|
|
1173
1439
|
linked.primaryToLinked.set(newPrimaryId, [id]);
|
|
1174
1440
|
}
|
|
@@ -1181,64 +1447,57 @@ function upsertLinkedItemNumeric(linked, item, foreignKeyGetter, spec) {
|
|
|
1181
1447
|
}
|
|
1182
1448
|
function removeLinkedItemNumeric(linked, linkedId, foreignKeyGetter) {
|
|
1183
1449
|
const existingItem = linked.linkedData.get(linkedId);
|
|
1184
|
-
if (!existingItem)
|
|
1450
|
+
if (!existingItem)
|
|
1185
1451
|
return false;
|
|
1186
|
-
}
|
|
1187
1452
|
const primaryId = foreignKeyGetter(existingItem);
|
|
1188
1453
|
linked.linkedData.delete(linkedId);
|
|
1189
|
-
linked.linkedMeta
|
|
1454
|
+
clearTokens(linked.linkedMeta, linkedId);
|
|
1190
1455
|
if (primaryId) {
|
|
1191
1456
|
const list = linked.primaryToLinked.get(primaryId);
|
|
1192
1457
|
if (list) {
|
|
1193
1458
|
const index = list.indexOf(linkedId);
|
|
1194
|
-
if (index !== -1)
|
|
1459
|
+
if (index !== -1)
|
|
1195
1460
|
list.splice(index, 1);
|
|
1196
|
-
}
|
|
1197
1461
|
}
|
|
1198
1462
|
}
|
|
1199
1463
|
return true;
|
|
1200
1464
|
}
|
|
1201
1465
|
function syncLinkedItemsForPrimaryNumeric(linked, primaryId, newLinkedItems, foreignKeyGetter, spec) {
|
|
1202
|
-
const result = {
|
|
1203
|
-
added: 0,
|
|
1204
|
-
updated: 0,
|
|
1205
|
-
removed: 0
|
|
1206
|
-
};
|
|
1466
|
+
const result = { added: 0, updated: 0, removed: 0 };
|
|
1207
1467
|
const tokensMap = createTokensMap();
|
|
1208
1468
|
const currentLinkedIds = new Set(linked.primaryToLinked.get(primaryId) || []);
|
|
1209
1469
|
const newLinkedIds = new Set;
|
|
1210
1470
|
for (const [id, item] of newLinkedItems) {
|
|
1211
|
-
if (foreignKeyGetter(item) === primaryId)
|
|
1471
|
+
if (foreignKeyGetter(item) === primaryId)
|
|
1212
1472
|
newLinkedIds.add(id);
|
|
1213
|
-
}
|
|
1214
1473
|
}
|
|
1215
1474
|
for (const id of currentLinkedIds) {
|
|
1216
1475
|
if (!newLinkedIds.has(id)) {
|
|
1217
|
-
|
|
1218
|
-
if (item) {
|
|
1476
|
+
if (linked.linkedData.has(id)) {
|
|
1219
1477
|
linked.linkedData.delete(id);
|
|
1220
|
-
linked.linkedMeta
|
|
1478
|
+
clearTokens(linked.linkedMeta, id);
|
|
1221
1479
|
result.removed++;
|
|
1222
1480
|
}
|
|
1223
1481
|
}
|
|
1224
1482
|
}
|
|
1225
1483
|
for (const id of newLinkedIds) {
|
|
1226
1484
|
const item = newLinkedItems.get(id);
|
|
1227
|
-
const
|
|
1485
|
+
const prepared = prepareObjectForSearchNumeric(item, spec, tokensMap);
|
|
1228
1486
|
if (currentLinkedIds.has(id)) {
|
|
1229
|
-
const
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1487
|
+
const existingSorted = linked.linkedMeta.sorted.get(id);
|
|
1488
|
+
const existingFirstN = linked.linkedMeta.unsorted.get(id);
|
|
1489
|
+
if (prepared !== undefined) {
|
|
1490
|
+
if (!existingSorted || !tokensEqual2(existingSorted, prepared.sorted) || !firstNEqual2(existingFirstN, prepared.firstN)) {
|
|
1491
|
+
applyOrClear(linked.linkedMeta, id, prepared);
|
|
1233
1492
|
result.updated++;
|
|
1234
1493
|
}
|
|
1494
|
+
} else {
|
|
1495
|
+
clearTokens(linked.linkedMeta, id);
|
|
1235
1496
|
}
|
|
1236
1497
|
linked.linkedData.set(id, item);
|
|
1237
1498
|
} else {
|
|
1238
1499
|
linked.linkedData.set(id, item);
|
|
1239
|
-
|
|
1240
|
-
linked.linkedMeta.set(id, tokens2);
|
|
1241
|
-
}
|
|
1500
|
+
applyOrClear(linked.linkedMeta, id, prepared);
|
|
1242
1501
|
result.added++;
|
|
1243
1502
|
}
|
|
1244
1503
|
}
|
|
@@ -1247,54 +1506,14 @@ function syncLinkedItemsForPrimaryNumeric(linked, primaryId, newLinkedItems, for
|
|
|
1247
1506
|
return result;
|
|
1248
1507
|
}
|
|
1249
1508
|
// src/common/numeric/searchAndRank.ts
|
|
1250
|
-
function
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
if (exactKeys[i] === query)
|
|
1257
|
-
return 1e5;
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1260
|
-
if (qTokens.length === 0)
|
|
1261
|
-
return 0;
|
|
1262
|
-
const primaryText = primaryTextFn(item) || "";
|
|
1263
|
-
const itemTokens = orderedTokenize(primaryText);
|
|
1264
|
-
if (itemTokens.length === 0)
|
|
1265
|
-
return 1;
|
|
1266
|
-
let qi = 0;
|
|
1267
|
-
const positions = [];
|
|
1268
|
-
for (let i = 0;i < itemTokens.length; i++) {
|
|
1269
|
-
if (qi < qTokens.length && itemTokens[i].startsWith(qTokens[qi])) {
|
|
1270
|
-
positions.push(i);
|
|
1271
|
-
qi++;
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
if (qi === 0)
|
|
1275
|
-
return 1;
|
|
1276
|
-
let score = 50;
|
|
1277
|
-
if (qi === qTokens.length)
|
|
1278
|
-
score += 100;
|
|
1279
|
-
if (positions[0] === 0)
|
|
1280
|
-
score += 50;
|
|
1281
|
-
let perfect = qi === qTokens.length;
|
|
1282
|
-
if (perfect) {
|
|
1283
|
-
for (let i = 0;i < positions.length; i++) {
|
|
1284
|
-
if (positions[i] !== i) {
|
|
1285
|
-
perfect = false;
|
|
1286
|
-
break;
|
|
1287
|
-
}
|
|
1288
|
-
}
|
|
1289
|
-
}
|
|
1290
|
-
if (perfect)
|
|
1291
|
-
score += 80;
|
|
1292
|
-
if (positions.length >= 2) {
|
|
1293
|
-
const span = positions[positions.length - 1] - positions[0] + 1;
|
|
1294
|
-
score += positions.length / span * 30;
|
|
1509
|
+
function tokenIdsToStrings(tokenIds) {
|
|
1510
|
+
if (tokenIds === undefined)
|
|
1511
|
+
return;
|
|
1512
|
+
const out = new Array(tokenIds.length);
|
|
1513
|
+
for (let i = 0;i < tokenIds.length; i++) {
|
|
1514
|
+
out[i] = tokens[tokenIds[i]] ?? "";
|
|
1295
1515
|
}
|
|
1296
|
-
|
|
1297
|
-
return score;
|
|
1516
|
+
return out;
|
|
1298
1517
|
}
|
|
1299
1518
|
function searchAndRankNumeric(query, data, metadata, options) {
|
|
1300
1519
|
const { primaryTextFn, exactKeysFn, limit, opts } = options;
|
|
@@ -1307,8 +1526,9 @@ function searchAndRankNumeric(query, data, metadata, options) {
|
|
|
1307
1526
|
const item = data.get(id);
|
|
1308
1527
|
if (!item)
|
|
1309
1528
|
continue;
|
|
1529
|
+
const itemTokens = tokenIdsToStrings(metadata.unsorted.get(id)) ?? orderedTokenize(primaryTextFn(item) || "");
|
|
1310
1530
|
const exactKeys = exactKeysFn?.(item);
|
|
1311
|
-
const score = scoreOne(
|
|
1531
|
+
const score = scoreOne(query, qTokens, itemTokens, exactKeys);
|
|
1312
1532
|
scored.push({ id, item, score });
|
|
1313
1533
|
}
|
|
1314
1534
|
scored.sort((x, y) => {
|
|
@@ -1332,6 +1552,13 @@ function tokensEqual3(a, b) {
|
|
|
1332
1552
|
}
|
|
1333
1553
|
return true;
|
|
1334
1554
|
}
|
|
1555
|
+
function firstNEqual3(a, b) {
|
|
1556
|
+
if (a === undefined && b === undefined)
|
|
1557
|
+
return true;
|
|
1558
|
+
if (a === undefined || b === undefined)
|
|
1559
|
+
return false;
|
|
1560
|
+
return tokensEqual3(a, b);
|
|
1561
|
+
}
|
|
1335
1562
|
|
|
1336
1563
|
class SearchUniverse {
|
|
1337
1564
|
collections = new Map;
|
|
@@ -1341,7 +1568,7 @@ class SearchUniverse {
|
|
|
1341
1568
|
}
|
|
1342
1569
|
const collection = {
|
|
1343
1570
|
data: new Map,
|
|
1344
|
-
metadata:
|
|
1571
|
+
metadata: emptyNumericSearchMetadata(),
|
|
1345
1572
|
config
|
|
1346
1573
|
};
|
|
1347
1574
|
if (config.linkedTo) {
|
|
@@ -1358,7 +1585,8 @@ class SearchUniverse {
|
|
|
1358
1585
|
loadCollection(name, items) {
|
|
1359
1586
|
const collection = this.getCollectionOrThrow(name);
|
|
1360
1587
|
collection.data.clear();
|
|
1361
|
-
collection.metadata.clear();
|
|
1588
|
+
collection.metadata.sorted.clear();
|
|
1589
|
+
collection.metadata.unsorted.clear();
|
|
1362
1590
|
if (collection.primaryToLinked) {
|
|
1363
1591
|
collection.primaryToLinked.clear();
|
|
1364
1592
|
}
|
|
@@ -1366,8 +1594,11 @@ class SearchUniverse {
|
|
|
1366
1594
|
collection.data.set(item._id, item);
|
|
1367
1595
|
}
|
|
1368
1596
|
const newMetadata = createSearchArrayMetadataNumeric(collection.data, collection.config.spec);
|
|
1369
|
-
for (const [id, tokens2] of newMetadata) {
|
|
1370
|
-
collection.metadata.set(id, tokens2);
|
|
1597
|
+
for (const [id, tokens2] of newMetadata.sorted) {
|
|
1598
|
+
collection.metadata.sorted.set(id, tokens2);
|
|
1599
|
+
}
|
|
1600
|
+
for (const [id, tokens2] of newMetadata.unsorted) {
|
|
1601
|
+
collection.metadata.unsorted.set(id, tokens2);
|
|
1371
1602
|
}
|
|
1372
1603
|
if (collection.config.linkedTo && collection.primaryToLinked) {
|
|
1373
1604
|
const { foreignKeyGetter } = collection.config.linkedTo;
|
|
@@ -1463,11 +1694,17 @@ class SearchUniverse {
|
|
|
1463
1694
|
collection.data.set(id, item);
|
|
1464
1695
|
const tokensMap = createTokensMap();
|
|
1465
1696
|
try {
|
|
1466
|
-
const
|
|
1467
|
-
if (
|
|
1468
|
-
collection.metadata.set(id,
|
|
1697
|
+
const prepared = prepareObjectForSearchNumeric(item, collection.config.spec, tokensMap);
|
|
1698
|
+
if (prepared !== undefined) {
|
|
1699
|
+
collection.metadata.sorted.set(id, prepared.sorted);
|
|
1700
|
+
if (prepared.firstN !== undefined) {
|
|
1701
|
+
collection.metadata.unsorted.set(id, prepared.firstN);
|
|
1702
|
+
} else {
|
|
1703
|
+
collection.metadata.unsorted.delete(id);
|
|
1704
|
+
}
|
|
1469
1705
|
} else {
|
|
1470
|
-
collection.metadata.delete(id);
|
|
1706
|
+
collection.metadata.sorted.delete(id);
|
|
1707
|
+
collection.metadata.unsorted.delete(id);
|
|
1471
1708
|
}
|
|
1472
1709
|
} finally {
|
|
1473
1710
|
clearTokensMap(tokensMap);
|
|
@@ -1521,7 +1758,8 @@ class SearchUniverse {
|
|
|
1521
1758
|
}
|
|
1522
1759
|
}
|
|
1523
1760
|
collection.data.delete(id);
|
|
1524
|
-
collection.metadata.delete(id);
|
|
1761
|
+
collection.metadata.sorted.delete(id);
|
|
1762
|
+
collection.metadata.unsorted.delete(id);
|
|
1525
1763
|
return true;
|
|
1526
1764
|
}
|
|
1527
1765
|
removeFromSearchMetadataBatch(collectionName, ids) {
|
|
@@ -1572,9 +1810,10 @@ class SearchUniverse {
|
|
|
1572
1810
|
}
|
|
1573
1811
|
}
|
|
1574
1812
|
}
|
|
1575
|
-
const hadMetadata = collection.metadata.has(id);
|
|
1813
|
+
const hadMetadata = collection.metadata.sorted.has(id);
|
|
1576
1814
|
collection.data.delete(id);
|
|
1577
|
-
collection.metadata.delete(id);
|
|
1815
|
+
collection.metadata.sorted.delete(id);
|
|
1816
|
+
collection.metadata.unsorted.delete(id);
|
|
1578
1817
|
if (hadMetadata) {
|
|
1579
1818
|
result.removed++;
|
|
1580
1819
|
result.removedIds.push(id);
|
|
@@ -1585,11 +1824,11 @@ class SearchUniverse {
|
|
|
1585
1824
|
for (const item of newItems) {
|
|
1586
1825
|
const id = item._id;
|
|
1587
1826
|
const existing = collection.data.get(id);
|
|
1588
|
-
const hadMetadata = collection.metadata.has(id);
|
|
1827
|
+
const hadMetadata = collection.metadata.sorted.has(id);
|
|
1589
1828
|
const shouldTokenize = !existing || !skipUpdateCheck;
|
|
1590
|
-
let
|
|
1829
|
+
let prepared;
|
|
1591
1830
|
if (shouldTokenize) {
|
|
1592
|
-
|
|
1831
|
+
prepared = prepareObjectForSearchNumeric(item, collection.config.spec, tokensMap);
|
|
1593
1832
|
}
|
|
1594
1833
|
if (fkGetter && collection.primaryToLinked) {
|
|
1595
1834
|
const newFk = fkGetter(item);
|
|
@@ -1619,20 +1858,30 @@ class SearchUniverse {
|
|
|
1619
1858
|
collection.data.set(id, item);
|
|
1620
1859
|
if (!shouldTokenize)
|
|
1621
1860
|
continue;
|
|
1622
|
-
if (
|
|
1861
|
+
if (prepared === undefined) {
|
|
1623
1862
|
if (hadMetadata) {
|
|
1624
|
-
collection.metadata.delete(id);
|
|
1863
|
+
collection.metadata.sorted.delete(id);
|
|
1864
|
+
collection.metadata.unsorted.delete(id);
|
|
1625
1865
|
result.removed++;
|
|
1626
1866
|
result.removedIds.push(id);
|
|
1627
1867
|
}
|
|
1628
1868
|
} else if (!hadMetadata) {
|
|
1629
|
-
collection.metadata.set(id,
|
|
1869
|
+
collection.metadata.sorted.set(id, prepared.sorted);
|
|
1870
|
+
if (prepared.firstN !== undefined) {
|
|
1871
|
+
collection.metadata.unsorted.set(id, prepared.firstN);
|
|
1872
|
+
}
|
|
1630
1873
|
result.added++;
|
|
1631
1874
|
result.addedIds.push(id);
|
|
1632
1875
|
} else {
|
|
1633
|
-
const
|
|
1634
|
-
|
|
1635
|
-
|
|
1876
|
+
const existingSorted = collection.metadata.sorted.get(id);
|
|
1877
|
+
const existingFirstN = collection.metadata.unsorted.get(id);
|
|
1878
|
+
if (!tokensEqual3(existingSorted, prepared.sorted) || !firstNEqual3(existingFirstN, prepared.firstN)) {
|
|
1879
|
+
collection.metadata.sorted.set(id, prepared.sorted);
|
|
1880
|
+
if (prepared.firstN !== undefined) {
|
|
1881
|
+
collection.metadata.unsorted.set(id, prepared.firstN);
|
|
1882
|
+
} else {
|
|
1883
|
+
collection.metadata.unsorted.delete(id);
|
|
1884
|
+
}
|
|
1636
1885
|
result.updated++;
|
|
1637
1886
|
result.updatedIds.push(id);
|
|
1638
1887
|
}
|
|
@@ -1711,7 +1960,8 @@ class SearchUniverse {
|
|
|
1711
1960
|
clear() {
|
|
1712
1961
|
for (const collection of this.collections.values()) {
|
|
1713
1962
|
collection.data.clear();
|
|
1714
|
-
collection.metadata.clear();
|
|
1963
|
+
collection.metadata.sorted.clear();
|
|
1964
|
+
collection.metadata.unsorted.clear();
|
|
1715
1965
|
if (collection.primaryToLinked) {
|
|
1716
1966
|
collection.primaryToLinked.clear();
|
|
1717
1967
|
}
|
|
@@ -1736,7 +1986,9 @@ export {
|
|
|
1736
1986
|
searchInDataReturnIdsNumeric as searchInData,
|
|
1737
1987
|
searchAndRankNumeric,
|
|
1738
1988
|
searchAndRankNumeric as searchAndRank,
|
|
1989
|
+
scoreOrderAndPresence,
|
|
1739
1990
|
scoreOne,
|
|
1991
|
+
scoreBag,
|
|
1740
1992
|
sanitiseString,
|
|
1741
1993
|
resetTokenRegistry,
|
|
1742
1994
|
removePrimaryItemNumeric as removePrimaryItem,
|
|
@@ -1772,6 +2024,8 @@ export {
|
|
|
1772
2024
|
allPreparedTokensMatch,
|
|
1773
2025
|
TOKEN_ID_MASK,
|
|
1774
2026
|
SearchUniverse,
|
|
2027
|
+
PREFIX_TO_MATCH_MODE,
|
|
2028
|
+
MATCH_MODE_PREFIXES,
|
|
1775
2029
|
MATCH_MODE_BITS,
|
|
1776
2030
|
DEFAULT_SEARCH_OPTS,
|
|
1777
2031
|
AugmentedMetadata
|