@lde/search-typesense 0.48.0 → 0.49.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/dist/collection-definition.js +22 -10
- package/dist/lookup.js +7 -4
- package/dist/query-compiler.js +1 -1
- package/dist/search.d.ts.map +1 -1
- package/dist/search.js +25 -2
- package/package.json +2 -2
|
@@ -209,12 +209,17 @@ function typesenseFields(searchType, field, defaultLocale, defaultSortingField,
|
|
|
209
209
|
// a membership filter on it exact (`compileMembership`).
|
|
210
210
|
facet: names.facet === field.name,
|
|
211
211
|
// Typesense answers a binned facet only on a field indexed for
|
|
212
|
-
// sorting, so a field declaring bins is, sortable or not.
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
// sorting, so a field declaring bins is, sortable or not. A lookup
|
|
213
|
+
// reading its literals as periods sorts on their bounds instead.
|
|
214
|
+
sort: names.period === undefined &&
|
|
215
|
+
(field.sortable === true ||
|
|
216
|
+
(field.facetable === true && isBinnedRangeFacet(field))),
|
|
215
217
|
// A `required` field is non-optional; so is the `default_sorting_field`,
|
|
216
|
-
// which Typesense requires to be present. Everything else may be absent
|
|
217
|
-
|
|
218
|
+
// which Typesense requires to be present. Everything else may be absent
|
|
219
|
+
// – a required lookup reading its literals as periods too, since its
|
|
220
|
+
// value may be a period alone, stored in a companion.
|
|
221
|
+
optional: (field.required !== true || names.period !== undefined) &&
|
|
222
|
+
field.name !== defaultSortingField,
|
|
218
223
|
...referenceDeclaration(searchType, field, schema, collectionNameFor),
|
|
219
224
|
},
|
|
220
225
|
];
|
|
@@ -246,10 +251,15 @@ function typesenseFields(searchType, field, defaultLocale, defaultSortingField,
|
|
|
246
251
|
if (names.precision !== undefined) {
|
|
247
252
|
fields.push(precisionField(names.precision));
|
|
248
253
|
}
|
|
254
|
+
// A lookup reading its literals as periods stores them as a `period` does.
|
|
255
|
+
if (names.period !== undefined) {
|
|
256
|
+
fields.push(...periodFields(field, names));
|
|
257
|
+
}
|
|
249
258
|
return fields;
|
|
250
259
|
}
|
|
251
260
|
/**
|
|
252
|
-
* A `period` field
|
|
261
|
+
* A `period` field – or the periods a lookup reads its literals as: its values
|
|
262
|
+
* verbatim, stored for output but never indexed –
|
|
253
263
|
* nothing filters or sorts on the text – and the two int64 bound companions
|
|
254
264
|
* ({@link physicalFields}) that filters and sorts read instead. The bounds are
|
|
255
265
|
* indexed for sorting whatever the field declares: a deployment may sort on a
|
|
@@ -257,14 +267,16 @@ function typesenseFields(searchType, field, defaultLocale, defaultSortingField,
|
|
|
257
267
|
* field costs little next to a collection rebuilt the day it becomes so.
|
|
258
268
|
*/
|
|
259
269
|
function periodFields(field, names) {
|
|
260
|
-
// Every period has bounds; `physicalFields` names them for no other
|
|
261
|
-
const { start, end } = names.period;
|
|
270
|
+
// Every period has bounds; `physicalFields` names them for no other field.
|
|
271
|
+
const { values, start, end } = names.period;
|
|
262
272
|
return [
|
|
263
273
|
{
|
|
264
|
-
name:
|
|
274
|
+
name: values,
|
|
265
275
|
type: typesenseValueType(field),
|
|
266
276
|
index: false,
|
|
267
|
-
optional
|
|
277
|
+
// A lookup’s periods are optional however `required` it is: its value
|
|
278
|
+
// may be a referent instead.
|
|
279
|
+
optional: field.required !== true || field.kind !== 'period',
|
|
268
280
|
},
|
|
269
281
|
...[start, end].map((name) => ({
|
|
270
282
|
name,
|
package/dist/lookup.js
CHANGED
|
@@ -161,10 +161,13 @@ function includeFields(target, wanted, below) {
|
|
|
161
161
|
}
|
|
162
162
|
else {
|
|
163
163
|
physical.add(field.name);
|
|
164
|
-
// A date is served at the precision its source gave, kept beside it
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
// A date is served at the precision its source gave, kept beside it,
|
|
165
|
+
// and a lookup with the periods it reads its literals as.
|
|
166
|
+
const { precision, period } = physicalFields(field);
|
|
167
|
+
for (const companion of [precision, period?.values]) {
|
|
168
|
+
if (companion !== undefined) {
|
|
169
|
+
physical.add(companion);
|
|
170
|
+
}
|
|
168
171
|
}
|
|
169
172
|
}
|
|
170
173
|
}
|
package/dist/query-compiler.js
CHANGED
|
@@ -334,7 +334,7 @@ function compileLeaf(criterion, searchType, schema, prefix = '') {
|
|
|
334
334
|
}
|
|
335
335
|
// A criterion whose operator does not match the field's kind (e.g. `range` on
|
|
336
336
|
// a keyword) would reach the engine as garbage syntax – skip it instead.
|
|
337
|
-
if (filterOperatorFor(field
|
|
337
|
+
if (filterOperatorFor(field) !== filterOperator(criterion)) {
|
|
338
338
|
return UNUSABLE;
|
|
339
339
|
}
|
|
340
340
|
if ('in' in criterion) {
|
package/dist/search.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAIL,KAAK,cAAc,EAMnB,KAAK,UAAU,EAGf,KAAK,YAAY,EAEjB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,UAAU,EAEf,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../src/search.ts"],"names":[],"mappings":"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"}
|
package/dist/search.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NESTED_DOCUMENT_TYPE, } from '@lde/search';
|
|
2
|
-
import { assertTypeInSchema, assertValidQuery, displayLangOf, facetableFields, facetSearches, fieldNamed, filterOn, inheritedFacetPolicies, isDatePrecision, isInlineReference, isBinnedRangeFacet, isUnsatisfiable, joinGraph, labelFieldOf, labelSourceNamesOf, labelTargetNamesOf, localLookupTargetsOf, nestedReferenceType, outputFields, physicalFields, referencedTargetsOf, referenceFields, storedFacetRanges, storedTargetOf, } from '@lde/search/adapter';
|
|
2
|
+
import { assertTypeInSchema, assertValidQuery, displayLangOf, facetableFields, facetSearches, fieldNamed, filterOn, inheritedFacetPolicies, isDatePrecision, isInlineReference, isBinnedRangeFacet, isUnsatisfiable, joinGraph, labelFieldOf, labelSourceNamesOf, labelTargetNamesOf, literalKindOf, localLookupTargetsOf, nestedReferenceType, outputFields, physicalFields, referencedTargetsOf, referenceFields, storedFacetRanges, storedTargetOf, } from '@lde/search/adapter';
|
|
3
3
|
import { buildSearchParams, escapeFilterValue, } from './query-compiler.js';
|
|
4
4
|
import { deriveCollectionName } from './collection-name.js';
|
|
5
5
|
import { resolveProjection, } from './lookup.js';
|
|
@@ -798,13 +798,36 @@ export function parseSearchResponse(response, searchType, labels, schema, refere
|
|
|
798
798
|
function reconstructDocument(flat, searchType, labels, schema, referents) {
|
|
799
799
|
const document = {};
|
|
800
800
|
for (const field of outputFields(searchType)) {
|
|
801
|
-
const value = logicalValue(flat, field, labels, schema, referents);
|
|
801
|
+
const value = withPeriods(flat, field, logicalValue(flat, field, labels, schema, referents));
|
|
802
802
|
if (value !== undefined) {
|
|
803
803
|
document[field.name] = value;
|
|
804
804
|
}
|
|
805
805
|
}
|
|
806
806
|
return document;
|
|
807
807
|
}
|
|
808
|
+
/**
|
|
809
|
+
* A lookup reading its literals as periods, with those periods added to its
|
|
810
|
+
* referents: one list in which each entry is a period, as stated, or a
|
|
811
|
+
* referent. A single-valued field stores only one of the two
|
|
812
|
+
* (`applyReferentsOrPeriods`). Any other field’s value is returned as it is.
|
|
813
|
+
*/
|
|
814
|
+
function withPeriods(flat, field, referents) {
|
|
815
|
+
const periods = literalKindOf(field) === 'period'
|
|
816
|
+
? physicalFields(field).period
|
|
817
|
+
: undefined;
|
|
818
|
+
if (periods === undefined) {
|
|
819
|
+
return referents;
|
|
820
|
+
}
|
|
821
|
+
const stored = flat[periods.values];
|
|
822
|
+
const values = (Array.isArray(stored) ? stored : [stored]).filter((value) => typeof value === 'string');
|
|
823
|
+
if (field.array !== true || values.length === 0) {
|
|
824
|
+
return values[0] ?? referents;
|
|
825
|
+
}
|
|
826
|
+
return [
|
|
827
|
+
...values,
|
|
828
|
+
...(referents ?? []),
|
|
829
|
+
];
|
|
830
|
+
}
|
|
808
831
|
function logicalValue(flat, field, labels, schema, referents) {
|
|
809
832
|
switch (field.kind) {
|
|
810
833
|
case 'text':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lde/search-typesense",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.49.0",
|
|
4
4
|
"description": "Typesense implementation of the @lde/search SearchEngine port: collection-schema builder, query compiler, label-resolving result reconstruction, and blue/green index lifecycle. Engine-specific (Typesense) but domain-agnostic.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "git+https://github.com/ldelements/lde.git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"!**/*.tsbuildinfo"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@lde/search": "^0.
|
|
28
|
+
"@lde/search": "^0.40.0",
|
|
29
29
|
"@lde/text-normalization": "^0.3.0",
|
|
30
30
|
"tslib": "^2.3.0",
|
|
31
31
|
"typesense": "^3.2.0"
|