@yoch/frozenminisearch 1.2.0 → 1.2.1
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/CHANGELOG.md +9 -0
- package/dist/cjs/index.cjs +69 -35
- package/dist/es/index.d.ts +1 -0
- package/dist/es/index.js +69 -35
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## v1.2.1 — `@yoch/frozenminisearch`
|
|
6
|
+
|
|
7
|
+
Patch release: lower search overhead when stored fields are disabled and fewer query-normalization allocations. No API or MSv5 wire-format changes.
|
|
8
|
+
|
|
9
|
+
### Improved
|
|
10
|
+
|
|
11
|
+
- **Search without `storeFields`** — skip stored-field reads during scoring and result finalization when the index has no stored fields (`storeFields: []`).
|
|
12
|
+
- **String query normalization** — pre-allocated term/spec buffers, hoisted per-query field boosts and match weights, and shared `termToQuerySpec` building (fewer intermediate arrays and closures).
|
|
13
|
+
|
|
5
14
|
## v1.2.0 — `@yoch/frozenminisearch`
|
|
6
15
|
|
|
7
16
|
Minor release: configurable MSv5 snapshot compression and Node 20 support.
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -260,7 +260,9 @@ function finalizeSearchResults(params) {
|
|
|
260
260
|
queryTerms: terms,
|
|
261
261
|
match,
|
|
262
262
|
};
|
|
263
|
-
|
|
263
|
+
if (getStoredFields != null) {
|
|
264
|
+
Object.assign(result, getStoredFields(docId));
|
|
265
|
+
}
|
|
264
266
|
if (filter == null || filter(result)) {
|
|
265
267
|
results.push(result);
|
|
266
268
|
}
|
|
@@ -4186,56 +4188,76 @@ function normalizeStringQuery(query, searchOptions, params) {
|
|
|
4186
4188
|
...params.globalSearchOptions,
|
|
4187
4189
|
...searchOptions,
|
|
4188
4190
|
};
|
|
4189
|
-
const
|
|
4190
|
-
|
|
4191
|
-
|
|
4191
|
+
const tokens = options.tokenize(query);
|
|
4192
|
+
const terms = [];
|
|
4193
|
+
for (const token of tokens) {
|
|
4194
|
+
const processed = options.processTerm(token);
|
|
4195
|
+
if (Array.isArray(processed)) {
|
|
4196
|
+
for (const term of processed) {
|
|
4197
|
+
if (term)
|
|
4198
|
+
terms.push(term);
|
|
4199
|
+
}
|
|
4200
|
+
}
|
|
4201
|
+
else if (processed) {
|
|
4202
|
+
terms.push(processed);
|
|
4203
|
+
}
|
|
4204
|
+
}
|
|
4205
|
+
const toSpec = termToQuerySpec(options);
|
|
4206
|
+
const specs = new Array(terms.length);
|
|
4207
|
+
for (let i = 0; i < terms.length; i++) {
|
|
4208
|
+
specs[i] = toSpec(terms[i], i, terms);
|
|
4209
|
+
}
|
|
4210
|
+
const { fuzzy: fuzzyWeight, prefix: prefixWeight } = {
|
|
4211
|
+
...defaultSearchOptions.weights,
|
|
4212
|
+
...options.weights,
|
|
4213
|
+
};
|
|
4192
4214
|
return {
|
|
4193
4215
|
options,
|
|
4194
|
-
specs
|
|
4216
|
+
specs,
|
|
4195
4217
|
operator: options.combineWith,
|
|
4218
|
+
fieldBoosts: fieldBoostsForQuery(options, params.fields),
|
|
4219
|
+
fuzzyWeight,
|
|
4220
|
+
prefixWeight,
|
|
4196
4221
|
};
|
|
4197
4222
|
}
|
|
4198
4223
|
function lazyIndexedTerm(indexView, termIndex) {
|
|
4199
4224
|
return { kind: 'lazy', resolve: () => indexView.resolveTermByIndex(termIndex) };
|
|
4200
4225
|
}
|
|
4201
|
-
function visitQuerySpecForScoring(query,
|
|
4226
|
+
function visitQuerySpecForScoring(query, normalized, params, visit) {
|
|
4202
4227
|
const { indexView } = params;
|
|
4203
|
-
const {
|
|
4204
|
-
const
|
|
4205
|
-
const maxDistance = maxFuzzyDistance(query, maxFuzzy);
|
|
4228
|
+
const { fuzzyWeight, options, prefixWeight } = normalized;
|
|
4229
|
+
const maxDistance = maxFuzzyDistance(query, options.maxFuzzy);
|
|
4206
4230
|
const exactTi = indexView.resolveTermIndex(query.term);
|
|
4207
4231
|
visit(exactTi == null ? undefined : indexView.fieldTermData(exactTi), query.term, 1);
|
|
4208
|
-
const seenPrefix = new Set();
|
|
4232
|
+
const seenPrefix = query.prefix && maxDistance ? new Set() : undefined;
|
|
4209
4233
|
if (query.prefix) {
|
|
4210
4234
|
for (const { termIndex, length } of indexView.getPrefixMatchesByIndex(query.term)) {
|
|
4211
4235
|
const distance = length - query.term.length;
|
|
4212
4236
|
if (!distance)
|
|
4213
4237
|
continue;
|
|
4214
|
-
seenPrefix.add(termIndex);
|
|
4238
|
+
seenPrefix === null || seenPrefix === void 0 ? void 0 : seenPrefix.add(termIndex);
|
|
4215
4239
|
visit(indexView.fieldTermData(termIndex), lazyIndexedTerm(indexView, termIndex), prefixWeight * length / (length + 0.3 * distance));
|
|
4216
4240
|
}
|
|
4217
4241
|
}
|
|
4218
4242
|
if (!maxDistance)
|
|
4219
4243
|
return;
|
|
4220
4244
|
for (const { termIndex, length, distance } of indexView.getFuzzyMatchesByIndex(query.term, maxDistance)) {
|
|
4221
|
-
if (!distance || seenPrefix.has(termIndex))
|
|
4245
|
+
if (!distance || (seenPrefix === null || seenPrefix === void 0 ? void 0 : seenPrefix.has(termIndex)))
|
|
4222
4246
|
continue;
|
|
4223
4247
|
visit(indexView.fieldTermData(termIndex), lazyIndexedTerm(indexView, termIndex), fuzzyWeight * length / (length + distance));
|
|
4224
4248
|
}
|
|
4225
4249
|
}
|
|
4226
|
-
function executeQuerySpecInternal(query,
|
|
4227
|
-
const
|
|
4228
|
-
const fieldBoosts = fieldBoostsForQuery(options, params.fields);
|
|
4250
|
+
function executeQuerySpecInternal(query, normalized, params, allowedDocs) {
|
|
4251
|
+
const { fieldBoosts, options } = normalized;
|
|
4229
4252
|
const termOptions = allowedDocs == null ? undefined : { allowedDocs };
|
|
4230
4253
|
const results = new Map();
|
|
4231
|
-
visitQuerySpecForScoring(query,
|
|
4254
|
+
visitQuerySpecForScoring(query, normalized, params, (data, derivedTerm, termWeight) => {
|
|
4232
4255
|
aggregateTerm(query.term, derivedTerm, termWeight, query.termBoost, data, fieldBoosts, params.aggregateContext, options.boostDocument, options.bm25, results, termOptions);
|
|
4233
4256
|
});
|
|
4234
4257
|
return results;
|
|
4235
4258
|
}
|
|
4236
|
-
function collectDocIdsForQuerySpec(query,
|
|
4237
|
-
const
|
|
4238
|
-
const fieldBoosts = fieldBoostsForQuery(options, params.fields);
|
|
4259
|
+
function collectDocIdsForQuerySpec(query, normalized, params, allowedDocs) {
|
|
4260
|
+
const { fieldBoosts, options } = normalized;
|
|
4239
4261
|
const docIds = new Set();
|
|
4240
4262
|
const { indexView, aggregateContext } = params;
|
|
4241
4263
|
const maxDistance = maxFuzzyDistance(query, options.maxFuzzy);
|
|
@@ -4243,19 +4265,19 @@ function collectDocIdsForQuerySpec(query, searchOptions, params, allowedDocs) {
|
|
|
4243
4265
|
if (exactTi != null) {
|
|
4244
4266
|
indexView.collectDocIds(exactTi, fieldBoosts, aggregateContext, docIds, allowedDocs);
|
|
4245
4267
|
}
|
|
4246
|
-
const seenPrefix = new Set();
|
|
4268
|
+
const seenPrefix = query.prefix && maxDistance ? new Set() : undefined;
|
|
4247
4269
|
if (query.prefix) {
|
|
4248
4270
|
for (const { termIndex, length } of indexView.getPrefixMatchesByIndex(query.term)) {
|
|
4249
4271
|
const distance = length - query.term.length;
|
|
4250
4272
|
if (!distance)
|
|
4251
4273
|
continue;
|
|
4252
|
-
seenPrefix.add(termIndex);
|
|
4274
|
+
seenPrefix === null || seenPrefix === void 0 ? void 0 : seenPrefix.add(termIndex);
|
|
4253
4275
|
indexView.collectDocIds(termIndex, fieldBoosts, aggregateContext, docIds, allowedDocs);
|
|
4254
4276
|
}
|
|
4255
4277
|
}
|
|
4256
4278
|
if (maxDistance) {
|
|
4257
4279
|
for (const { termIndex, distance } of indexView.getFuzzyMatchesByIndex(query.term, maxDistance)) {
|
|
4258
|
-
if (!distance || seenPrefix.has(termIndex))
|
|
4280
|
+
if (!distance || (seenPrefix === null || seenPrefix === void 0 ? void 0 : seenPrefix.has(termIndex)))
|
|
4259
4281
|
continue;
|
|
4260
4282
|
indexView.collectDocIds(termIndex, fieldBoosts, aggregateContext, docIds, allowedDocs);
|
|
4261
4283
|
}
|
|
@@ -4386,14 +4408,15 @@ function collectDocIdsForQueryInternal(query, searchOptions, params, allowedDocs
|
|
|
4386
4408
|
if (typeof query !== 'string') {
|
|
4387
4409
|
throw new Error('FrozenMiniSearch: invalid query');
|
|
4388
4410
|
}
|
|
4389
|
-
const
|
|
4411
|
+
const normalized = normalizeStringQuery(query, searchOptions, params);
|
|
4412
|
+
const { specs, operator } = normalized;
|
|
4390
4413
|
const combineWith = (operator !== null && operator !== void 0 ? operator : params.globalSearchOptions.combineWith);
|
|
4391
4414
|
if (specs.length <= 1) {
|
|
4392
4415
|
return specs.length === 1
|
|
4393
|
-
? collectDocIdsForQuerySpec(specs[0],
|
|
4416
|
+
? collectDocIdsForQuerySpec(specs[0], normalized, params, allowedDocs)
|
|
4394
4417
|
: new Set();
|
|
4395
4418
|
}
|
|
4396
|
-
return collectCombinedDocIds(specs, combineWith, (spec, branchAllowed) => collectDocIdsForQuerySpec(spec,
|
|
4419
|
+
return collectCombinedDocIds(specs, combineWith, (spec, branchAllowed) => collectDocIdsForQuerySpec(spec, normalized, params, branchAllowed), allowedDocs);
|
|
4397
4420
|
}
|
|
4398
4421
|
function executeWildcardQuery(searchOptions, params) {
|
|
4399
4422
|
const results = new Map();
|
|
@@ -4423,12 +4446,13 @@ function executeQueryInternal(query, searchOptions, params, allowedDocs, run) {
|
|
|
4423
4446
|
if (typeof query !== 'string') {
|
|
4424
4447
|
throw new Error('FrozenMiniSearch: invalid query');
|
|
4425
4448
|
}
|
|
4426
|
-
const
|
|
4449
|
+
const normalized = normalizeStringQuery(query, searchOptions, params);
|
|
4450
|
+
const { specs, operator } = normalized;
|
|
4427
4451
|
const combineWith = (operator !== null && operator !== void 0 ? operator : params.globalSearchOptions.combineWith);
|
|
4428
4452
|
if (useGatedEvaluation(run, specs.length, combineWith, false)) {
|
|
4429
|
-
return executeCombinedBranches(specs, combineWith, params, (spec, branchAllowed) => executeQuerySpecInternal(spec,
|
|
4453
|
+
return executeCombinedBranches(specs, combineWith, params, (spec, branchAllowed) => executeQuerySpecInternal(spec, normalized, params, branchAllowed), (spec, branchAllowed) => collectDocIdsForQuerySpec(spec, normalized, params, branchAllowed), allowedDocs);
|
|
4430
4454
|
}
|
|
4431
|
-
const results = specs.map(spec => executeQuerySpecInternal(spec,
|
|
4455
|
+
const results = specs.map(spec => executeQuerySpecInternal(spec, normalized, params, allowedDocs));
|
|
4432
4456
|
return combineResults(results, combineWith);
|
|
4433
4457
|
}
|
|
4434
4458
|
function executeQuery(query, searchOptions, params) {
|
|
@@ -4619,6 +4643,7 @@ function materializeOwnedSnapshot(params, mode) {
|
|
|
4619
4643
|
function frozenMemoryBreakdown(frozen) {
|
|
4620
4644
|
return frozen.memoryBreakdown();
|
|
4621
4645
|
}
|
|
4646
|
+
const noStoredFields = () => undefined;
|
|
4622
4647
|
function assertFieldsMatchSnapshot(optionsFields, snapFieldIds) {
|
|
4623
4648
|
const snapNames = Object.keys(snapFieldIds).sort();
|
|
4624
4649
|
const optNames = [...optionsFields].sort();
|
|
@@ -4672,24 +4697,31 @@ class FrozenMiniSearch {
|
|
|
4672
4697
|
this._termCount = params.termCount;
|
|
4673
4698
|
this._postings = params.postings;
|
|
4674
4699
|
this._fieldTermFlyweight = createFrozenFieldTermFlyweight(this._postings);
|
|
4700
|
+
this._hasStoredFields = this._storedFields.kind !== 'none';
|
|
4675
4701
|
this._aggregateContext = {
|
|
4676
4702
|
documentCount: this._documentCount,
|
|
4677
4703
|
avgFieldLength: this._avgFieldLength,
|
|
4678
4704
|
fieldIds: this._fieldIds,
|
|
4679
4705
|
getFieldLength: (docId, fieldId) => this.getFieldLength(docId, fieldId),
|
|
4680
4706
|
getExternalId: docId => this._externalIds[docId],
|
|
4681
|
-
getStoredFields:
|
|
4707
|
+
getStoredFields: this._hasStoredFields
|
|
4708
|
+
? docId => readStoredFields(this._storedFields, docId)
|
|
4709
|
+
: noStoredFields,
|
|
4682
4710
|
};
|
|
4683
4711
|
this._queryEngineParams = {
|
|
4684
4712
|
fields: this._options.fields,
|
|
4685
4713
|
globalSearchOptions: this._options.searchOptions,
|
|
4686
4714
|
tokenize: this._options.tokenize,
|
|
4687
4715
|
processTerm: this._options.processTerm,
|
|
4688
|
-
indexView: createFrozenQueryIndexView(this._index, this._postings, this._fieldTermFlyweight,
|
|
4689
|
-
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4716
|
+
indexView: createFrozenQueryIndexView(this._index, this._postings, this._fieldTermFlyweight, this._hasStoredFields
|
|
4717
|
+
? (callback) => {
|
|
4718
|
+
forEachLiveShortId(this._nextId, this._externalIds, (shortId, id) => {
|
|
4719
|
+
callback(shortId, id, readStoredFields(this._storedFields, shortId));
|
|
4720
|
+
});
|
|
4721
|
+
}
|
|
4722
|
+
: (callback) => {
|
|
4723
|
+
forEachLiveShortId(this._nextId, this._externalIds, callback);
|
|
4724
|
+
}),
|
|
4693
4725
|
aggregateContext: this._aggregateContext,
|
|
4694
4726
|
};
|
|
4695
4727
|
}
|
|
@@ -4746,7 +4778,9 @@ class FrozenMiniSearch {
|
|
|
4746
4778
|
return shortId == null ? undefined : readStoredFields(this._storedFields, shortId);
|
|
4747
4779
|
}
|
|
4748
4780
|
search(query, searchOptions = {}) {
|
|
4749
|
-
return finalizeRawSearchResults(this.executeQuery(query, searchOptions), query, searchOptions, this._options.searchOptions, docId => this._externalIds[docId],
|
|
4781
|
+
return finalizeRawSearchResults(this.executeQuery(query, searchOptions), query, searchOptions, this._options.searchOptions, docId => this._externalIds[docId], this._hasStoredFields
|
|
4782
|
+
? docId => readStoredFields(this._storedFields, docId)
|
|
4783
|
+
: undefined);
|
|
4750
4784
|
}
|
|
4751
4785
|
autoSuggest(queryString, options = {}) {
|
|
4752
4786
|
const merged = { ...this._options.autoSuggestOptions, ...options };
|
package/dist/es/index.d.ts
CHANGED
|
@@ -600,6 +600,7 @@ declare class FrozenMiniSearch<T = any> {
|
|
|
600
600
|
private readonly _fieldTermFlyweight;
|
|
601
601
|
private readonly _aggregateContext;
|
|
602
602
|
private readonly _queryEngineParams;
|
|
603
|
+
private readonly _hasStoredFields;
|
|
603
604
|
constructor(params: FrozenAssembleParams<T>);
|
|
604
605
|
static readonly wildcard: typeof WILDCARD_QUERY;
|
|
605
606
|
get documentCount(): number;
|
package/dist/es/index.js
CHANGED
|
@@ -256,7 +256,9 @@ function finalizeSearchResults(params) {
|
|
|
256
256
|
queryTerms: terms,
|
|
257
257
|
match,
|
|
258
258
|
};
|
|
259
|
-
|
|
259
|
+
if (getStoredFields != null) {
|
|
260
|
+
Object.assign(result, getStoredFields(docId));
|
|
261
|
+
}
|
|
260
262
|
if (filter == null || filter(result)) {
|
|
261
263
|
results.push(result);
|
|
262
264
|
}
|
|
@@ -4182,56 +4184,76 @@ function normalizeStringQuery(query, searchOptions, params) {
|
|
|
4182
4184
|
...params.globalSearchOptions,
|
|
4183
4185
|
...searchOptions,
|
|
4184
4186
|
};
|
|
4185
|
-
const
|
|
4186
|
-
|
|
4187
|
-
|
|
4187
|
+
const tokens = options.tokenize(query);
|
|
4188
|
+
const terms = [];
|
|
4189
|
+
for (const token of tokens) {
|
|
4190
|
+
const processed = options.processTerm(token);
|
|
4191
|
+
if (Array.isArray(processed)) {
|
|
4192
|
+
for (const term of processed) {
|
|
4193
|
+
if (term)
|
|
4194
|
+
terms.push(term);
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
else if (processed) {
|
|
4198
|
+
terms.push(processed);
|
|
4199
|
+
}
|
|
4200
|
+
}
|
|
4201
|
+
const toSpec = termToQuerySpec(options);
|
|
4202
|
+
const specs = new Array(terms.length);
|
|
4203
|
+
for (let i = 0; i < terms.length; i++) {
|
|
4204
|
+
specs[i] = toSpec(terms[i], i, terms);
|
|
4205
|
+
}
|
|
4206
|
+
const { fuzzy: fuzzyWeight, prefix: prefixWeight } = {
|
|
4207
|
+
...defaultSearchOptions.weights,
|
|
4208
|
+
...options.weights,
|
|
4209
|
+
};
|
|
4188
4210
|
return {
|
|
4189
4211
|
options,
|
|
4190
|
-
specs
|
|
4212
|
+
specs,
|
|
4191
4213
|
operator: options.combineWith,
|
|
4214
|
+
fieldBoosts: fieldBoostsForQuery(options, params.fields),
|
|
4215
|
+
fuzzyWeight,
|
|
4216
|
+
prefixWeight,
|
|
4192
4217
|
};
|
|
4193
4218
|
}
|
|
4194
4219
|
function lazyIndexedTerm(indexView, termIndex) {
|
|
4195
4220
|
return { kind: 'lazy', resolve: () => indexView.resolveTermByIndex(termIndex) };
|
|
4196
4221
|
}
|
|
4197
|
-
function visitQuerySpecForScoring(query,
|
|
4222
|
+
function visitQuerySpecForScoring(query, normalized, params, visit) {
|
|
4198
4223
|
const { indexView } = params;
|
|
4199
|
-
const {
|
|
4200
|
-
const
|
|
4201
|
-
const maxDistance = maxFuzzyDistance(query, maxFuzzy);
|
|
4224
|
+
const { fuzzyWeight, options, prefixWeight } = normalized;
|
|
4225
|
+
const maxDistance = maxFuzzyDistance(query, options.maxFuzzy);
|
|
4202
4226
|
const exactTi = indexView.resolveTermIndex(query.term);
|
|
4203
4227
|
visit(exactTi == null ? undefined : indexView.fieldTermData(exactTi), query.term, 1);
|
|
4204
|
-
const seenPrefix = new Set();
|
|
4228
|
+
const seenPrefix = query.prefix && maxDistance ? new Set() : undefined;
|
|
4205
4229
|
if (query.prefix) {
|
|
4206
4230
|
for (const { termIndex, length } of indexView.getPrefixMatchesByIndex(query.term)) {
|
|
4207
4231
|
const distance = length - query.term.length;
|
|
4208
4232
|
if (!distance)
|
|
4209
4233
|
continue;
|
|
4210
|
-
seenPrefix.add(termIndex);
|
|
4234
|
+
seenPrefix === null || seenPrefix === void 0 ? void 0 : seenPrefix.add(termIndex);
|
|
4211
4235
|
visit(indexView.fieldTermData(termIndex), lazyIndexedTerm(indexView, termIndex), prefixWeight * length / (length + 0.3 * distance));
|
|
4212
4236
|
}
|
|
4213
4237
|
}
|
|
4214
4238
|
if (!maxDistance)
|
|
4215
4239
|
return;
|
|
4216
4240
|
for (const { termIndex, length, distance } of indexView.getFuzzyMatchesByIndex(query.term, maxDistance)) {
|
|
4217
|
-
if (!distance || seenPrefix.has(termIndex))
|
|
4241
|
+
if (!distance || (seenPrefix === null || seenPrefix === void 0 ? void 0 : seenPrefix.has(termIndex)))
|
|
4218
4242
|
continue;
|
|
4219
4243
|
visit(indexView.fieldTermData(termIndex), lazyIndexedTerm(indexView, termIndex), fuzzyWeight * length / (length + distance));
|
|
4220
4244
|
}
|
|
4221
4245
|
}
|
|
4222
|
-
function executeQuerySpecInternal(query,
|
|
4223
|
-
const
|
|
4224
|
-
const fieldBoosts = fieldBoostsForQuery(options, params.fields);
|
|
4246
|
+
function executeQuerySpecInternal(query, normalized, params, allowedDocs) {
|
|
4247
|
+
const { fieldBoosts, options } = normalized;
|
|
4225
4248
|
const termOptions = allowedDocs == null ? undefined : { allowedDocs };
|
|
4226
4249
|
const results = new Map();
|
|
4227
|
-
visitQuerySpecForScoring(query,
|
|
4250
|
+
visitQuerySpecForScoring(query, normalized, params, (data, derivedTerm, termWeight) => {
|
|
4228
4251
|
aggregateTerm(query.term, derivedTerm, termWeight, query.termBoost, data, fieldBoosts, params.aggregateContext, options.boostDocument, options.bm25, results, termOptions);
|
|
4229
4252
|
});
|
|
4230
4253
|
return results;
|
|
4231
4254
|
}
|
|
4232
|
-
function collectDocIdsForQuerySpec(query,
|
|
4233
|
-
const
|
|
4234
|
-
const fieldBoosts = fieldBoostsForQuery(options, params.fields);
|
|
4255
|
+
function collectDocIdsForQuerySpec(query, normalized, params, allowedDocs) {
|
|
4256
|
+
const { fieldBoosts, options } = normalized;
|
|
4235
4257
|
const docIds = new Set();
|
|
4236
4258
|
const { indexView, aggregateContext } = params;
|
|
4237
4259
|
const maxDistance = maxFuzzyDistance(query, options.maxFuzzy);
|
|
@@ -4239,19 +4261,19 @@ function collectDocIdsForQuerySpec(query, searchOptions, params, allowedDocs) {
|
|
|
4239
4261
|
if (exactTi != null) {
|
|
4240
4262
|
indexView.collectDocIds(exactTi, fieldBoosts, aggregateContext, docIds, allowedDocs);
|
|
4241
4263
|
}
|
|
4242
|
-
const seenPrefix = new Set();
|
|
4264
|
+
const seenPrefix = query.prefix && maxDistance ? new Set() : undefined;
|
|
4243
4265
|
if (query.prefix) {
|
|
4244
4266
|
for (const { termIndex, length } of indexView.getPrefixMatchesByIndex(query.term)) {
|
|
4245
4267
|
const distance = length - query.term.length;
|
|
4246
4268
|
if (!distance)
|
|
4247
4269
|
continue;
|
|
4248
|
-
seenPrefix.add(termIndex);
|
|
4270
|
+
seenPrefix === null || seenPrefix === void 0 ? void 0 : seenPrefix.add(termIndex);
|
|
4249
4271
|
indexView.collectDocIds(termIndex, fieldBoosts, aggregateContext, docIds, allowedDocs);
|
|
4250
4272
|
}
|
|
4251
4273
|
}
|
|
4252
4274
|
if (maxDistance) {
|
|
4253
4275
|
for (const { termIndex, distance } of indexView.getFuzzyMatchesByIndex(query.term, maxDistance)) {
|
|
4254
|
-
if (!distance || seenPrefix.has(termIndex))
|
|
4276
|
+
if (!distance || (seenPrefix === null || seenPrefix === void 0 ? void 0 : seenPrefix.has(termIndex)))
|
|
4255
4277
|
continue;
|
|
4256
4278
|
indexView.collectDocIds(termIndex, fieldBoosts, aggregateContext, docIds, allowedDocs);
|
|
4257
4279
|
}
|
|
@@ -4382,14 +4404,15 @@ function collectDocIdsForQueryInternal(query, searchOptions, params, allowedDocs
|
|
|
4382
4404
|
if (typeof query !== 'string') {
|
|
4383
4405
|
throw new Error('FrozenMiniSearch: invalid query');
|
|
4384
4406
|
}
|
|
4385
|
-
const
|
|
4407
|
+
const normalized = normalizeStringQuery(query, searchOptions, params);
|
|
4408
|
+
const { specs, operator } = normalized;
|
|
4386
4409
|
const combineWith = (operator !== null && operator !== void 0 ? operator : params.globalSearchOptions.combineWith);
|
|
4387
4410
|
if (specs.length <= 1) {
|
|
4388
4411
|
return specs.length === 1
|
|
4389
|
-
? collectDocIdsForQuerySpec(specs[0],
|
|
4412
|
+
? collectDocIdsForQuerySpec(specs[0], normalized, params, allowedDocs)
|
|
4390
4413
|
: new Set();
|
|
4391
4414
|
}
|
|
4392
|
-
return collectCombinedDocIds(specs, combineWith, (spec, branchAllowed) => collectDocIdsForQuerySpec(spec,
|
|
4415
|
+
return collectCombinedDocIds(specs, combineWith, (spec, branchAllowed) => collectDocIdsForQuerySpec(spec, normalized, params, branchAllowed), allowedDocs);
|
|
4393
4416
|
}
|
|
4394
4417
|
function executeWildcardQuery(searchOptions, params) {
|
|
4395
4418
|
const results = new Map();
|
|
@@ -4419,12 +4442,13 @@ function executeQueryInternal(query, searchOptions, params, allowedDocs, run) {
|
|
|
4419
4442
|
if (typeof query !== 'string') {
|
|
4420
4443
|
throw new Error('FrozenMiniSearch: invalid query');
|
|
4421
4444
|
}
|
|
4422
|
-
const
|
|
4445
|
+
const normalized = normalizeStringQuery(query, searchOptions, params);
|
|
4446
|
+
const { specs, operator } = normalized;
|
|
4423
4447
|
const combineWith = (operator !== null && operator !== void 0 ? operator : params.globalSearchOptions.combineWith);
|
|
4424
4448
|
if (useGatedEvaluation(run, specs.length, combineWith, false)) {
|
|
4425
|
-
return executeCombinedBranches(specs, combineWith, params, (spec, branchAllowed) => executeQuerySpecInternal(spec,
|
|
4449
|
+
return executeCombinedBranches(specs, combineWith, params, (spec, branchAllowed) => executeQuerySpecInternal(spec, normalized, params, branchAllowed), (spec, branchAllowed) => collectDocIdsForQuerySpec(spec, normalized, params, branchAllowed), allowedDocs);
|
|
4426
4450
|
}
|
|
4427
|
-
const results = specs.map(spec => executeQuerySpecInternal(spec,
|
|
4451
|
+
const results = specs.map(spec => executeQuerySpecInternal(spec, normalized, params, allowedDocs));
|
|
4428
4452
|
return combineResults(results, combineWith);
|
|
4429
4453
|
}
|
|
4430
4454
|
function executeQuery(query, searchOptions, params) {
|
|
@@ -4615,6 +4639,7 @@ function materializeOwnedSnapshot(params, mode) {
|
|
|
4615
4639
|
function frozenMemoryBreakdown(frozen) {
|
|
4616
4640
|
return frozen.memoryBreakdown();
|
|
4617
4641
|
}
|
|
4642
|
+
const noStoredFields = () => undefined;
|
|
4618
4643
|
function assertFieldsMatchSnapshot(optionsFields, snapFieldIds) {
|
|
4619
4644
|
const snapNames = Object.keys(snapFieldIds).sort();
|
|
4620
4645
|
const optNames = [...optionsFields].sort();
|
|
@@ -4668,24 +4693,31 @@ class FrozenMiniSearch {
|
|
|
4668
4693
|
this._termCount = params.termCount;
|
|
4669
4694
|
this._postings = params.postings;
|
|
4670
4695
|
this._fieldTermFlyweight = createFrozenFieldTermFlyweight(this._postings);
|
|
4696
|
+
this._hasStoredFields = this._storedFields.kind !== 'none';
|
|
4671
4697
|
this._aggregateContext = {
|
|
4672
4698
|
documentCount: this._documentCount,
|
|
4673
4699
|
avgFieldLength: this._avgFieldLength,
|
|
4674
4700
|
fieldIds: this._fieldIds,
|
|
4675
4701
|
getFieldLength: (docId, fieldId) => this.getFieldLength(docId, fieldId),
|
|
4676
4702
|
getExternalId: docId => this._externalIds[docId],
|
|
4677
|
-
getStoredFields:
|
|
4703
|
+
getStoredFields: this._hasStoredFields
|
|
4704
|
+
? docId => readStoredFields(this._storedFields, docId)
|
|
4705
|
+
: noStoredFields,
|
|
4678
4706
|
};
|
|
4679
4707
|
this._queryEngineParams = {
|
|
4680
4708
|
fields: this._options.fields,
|
|
4681
4709
|
globalSearchOptions: this._options.searchOptions,
|
|
4682
4710
|
tokenize: this._options.tokenize,
|
|
4683
4711
|
processTerm: this._options.processTerm,
|
|
4684
|
-
indexView: createFrozenQueryIndexView(this._index, this._postings, this._fieldTermFlyweight,
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4712
|
+
indexView: createFrozenQueryIndexView(this._index, this._postings, this._fieldTermFlyweight, this._hasStoredFields
|
|
4713
|
+
? (callback) => {
|
|
4714
|
+
forEachLiveShortId(this._nextId, this._externalIds, (shortId, id) => {
|
|
4715
|
+
callback(shortId, id, readStoredFields(this._storedFields, shortId));
|
|
4716
|
+
});
|
|
4717
|
+
}
|
|
4718
|
+
: (callback) => {
|
|
4719
|
+
forEachLiveShortId(this._nextId, this._externalIds, callback);
|
|
4720
|
+
}),
|
|
4689
4721
|
aggregateContext: this._aggregateContext,
|
|
4690
4722
|
};
|
|
4691
4723
|
}
|
|
@@ -4742,7 +4774,9 @@ class FrozenMiniSearch {
|
|
|
4742
4774
|
return shortId == null ? undefined : readStoredFields(this._storedFields, shortId);
|
|
4743
4775
|
}
|
|
4744
4776
|
search(query, searchOptions = {}) {
|
|
4745
|
-
return finalizeRawSearchResults(this.executeQuery(query, searchOptions), query, searchOptions, this._options.searchOptions, docId => this._externalIds[docId],
|
|
4777
|
+
return finalizeRawSearchResults(this.executeQuery(query, searchOptions), query, searchOptions, this._options.searchOptions, docId => this._externalIds[docId], this._hasStoredFields
|
|
4778
|
+
? docId => readStoredFields(this._storedFields, docId)
|
|
4779
|
+
: undefined);
|
|
4746
4780
|
}
|
|
4747
4781
|
autoSuggest(queryString, options = {}) {
|
|
4748
4782
|
const merged = { ...this._options.autoSuggestOptions, ...options };
|
package/package.json
CHANGED