@lde/search 0.24.1 → 0.24.2

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.
Files changed (2) hide show
  1. package/dist/project.js +25 -10
  2. package/package.json +1 -1
package/dist/project.js CHANGED
@@ -302,6 +302,17 @@ function referenceValues(node, alias, field, schema) {
302
302
  * `sortable`) stay on the declared `locales`, which drive the indexed, stemmed,
303
303
  * weighted fanout; a value in an undeclared language is not indexed. Absent
304
304
  * languages emit nothing.
305
+ *
306
+ * The two companions differ in what an absent language means. A search query
307
+ * fans out over *every* locale key at once, so a document titled in one
308
+ * language is found whichever language the reader asks in. A sort names a
309
+ * **single** key, so a locale key left empty is not “no value in Dutch” – it is
310
+ * the empty string, which ties with every other document missing that language
311
+ * and leaves them in relevance order. Each locale’s sort key therefore falls
312
+ * back to the document’s first value in `locales` order: a collection of
313
+ * untagged titles sorts by title in a Dutch request rather than not at all.
314
+ * Ordering across languages is approximate by nature; a total order over the
315
+ * titles a reader actually sees beats a partial one over the tagged few.
305
316
  */
306
317
  function applyText(document, values, field) {
307
318
  if (field.output) {
@@ -319,18 +330,22 @@ function applyText(document, values, field) {
319
330
  // here it simply indexes nothing.
320
331
  if (field.searchable !== undefined || field.sortable === true) {
321
332
  const names = physicalFields(field);
322
- field.locales.forEach((locale, index) => {
323
- const localeValues = values
324
- .filter((value) => value.lang === locale)
325
- .map((value) => value.value);
326
- if (localeValues.length === 0) {
327
- return;
328
- }
329
- if (field.searchable) {
333
+ const valuesPerLocale = field.locales.map((locale) => values
334
+ .filter((value) => value.lang === locale)
335
+ .map((value) => value.value));
336
+ // What every locale’s sort key falls back to: the document’s first value
337
+ // in `locales` order, which is the declaration’s own statement of which
338
+ // language stands in for the others.
339
+ const fallbackSortValue = valuesPerLocale.find((localeValues) => localeValues.length > 0)?.[0];
340
+ valuesPerLocale.forEach((localeValues, index) => {
341
+ if (field.searchable !== undefined && localeValues.length > 0) {
330
342
  setString(document, names.search[index], foldedSearchValue(localeValues));
331
343
  }
332
- if (field.sortable) {
333
- setString(document, names.sort[index], fold(localeValues[0]));
344
+ if (field.sortable === true) {
345
+ const sortValue = localeValues[0] ?? fallbackSortValue;
346
+ if (sortValue !== undefined) {
347
+ setString(document, names.sort[index], fold(sortValue));
348
+ }
334
349
  }
335
350
  });
336
351
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lde/search",
3
- "version": "0.24.1",
3
+ "version": "0.24.2",
4
4
  "description": "Engine- and domain-agnostic core for RDF-backed search: a unified declarative field model (SearchField/SearchType/SearchSchema), a neutral query IR, the SearchEngine port with logical result types, and a streaming CONSTRUCT-to-document projection. Bakes in no engine, protocol, or domain.",
5
5
  "repository": {
6
6
  "url": "git+https://github.com/ldelements/lde.git",