« get me outta code hell

client: search particle query permutations - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/static/js/search-worker.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2024-05-06 12:30:09 -0300
committer(quasar) nebula <qznebula@protonmail.com>2024-05-31 12:11:50 -0300
commite1b340cf9693ecd1436260509e91680078d6ec98 (patch)
tree6ad87333c090350a1526dc9e38841f67cea3c421 /src/static/js/search-worker.js
parent2af0bf5b9a30abf28db68c8c3e54c48c722e6c14 (diff)
client: search particle query permutations
Diffstat (limited to 'src/static/js/search-worker.js')
-rw-r--r--src/static/js/search-worker.js95
1 files changed, 72 insertions, 23 deletions
diff --git a/src/static/js/search-worker.js b/src/static/js/search-worker.js
index 028b27c3..78814c20 100644
--- a/src/static/js/search-worker.js
+++ b/src/static/js/search-worker.js
@@ -1,5 +1,6 @@
 import {makeSearchIndex, searchSpec} from '../shared-util/search-spec.js';
-import {empty, unique, withEntries} from '../shared-util/sugar.js';
+import {empty, groupArray, stitchArrays, unique, withEntries}
+  from '../shared-util/sugar.js';
 
 import FlexSearch from '../lib/flexsearch/flexsearch.bundle.module.min.js';
 
@@ -117,12 +118,34 @@ function performSearchAction({query, options}) {
 
 function queryGenericIndex(index, query, options) {
   const terms = query.split(' ');
+
   const particles = particulate(terms);
-  console.log(particles);
 
-  const boilerplate = queryBoilerplate(index, query, options);
+  const groupedParticles =
+    groupArray(particles, ({length}) => length);
+
+  const queriesBy = keys =>
+    groupedParticles
+      .get(keys.length)
+      .flatMap(permutations)
+      .map(values => values.map(({terms}) => terms.join(' ')))
+      .map(values => Object.fromEntries(stitchArrays([keys, values])));
+
+  console.log(
+    queriesBy(['primaryName'])
+      .map(l => JSON.stringify(l))
+      .join('\n'));
+
+  console.log(
+    queriesBy(['primaryName', 'contributors'])
+      .map(l => JSON.stringify(l))
+      .join('\n'));
 
-  const {primaryName} = boilerplate.fieldResults;
+  const boilerplate = queryBoilerplate(index);
+
+  const {fieldResults} = boilerplate.query(query, options);
+
+  const {primaryName} = fieldResults;
 
   return boilerplate.constitute(primaryName);
 }
@@ -153,30 +176,56 @@ function particulate(terms) {
   return results;
 }
 
-function queryBoilerplate(index, query, options) {
-  const rawResults =
-    index.search(query, options);
-
-  const fieldResults =
-    Object.fromEntries(
-      rawResults
-        .map(({field, result}) => [
-          field,
-          result.map(({id}) => id),
-        ]));
+// This function doesn't even come close to "performant",
+// but it only operates on small data here.
+function permutations(array) {
+  switch (array.length) {
+    case 0:
+      return [];
 
-  const idToDoc =
-    Object.fromEntries(
-      rawResults
-        .flatMap(({result}) => result)
-        .map(({id, doc}) => [id, doc]));
+    case 1:
+      return [array];
+
+    default:
+      return array.flatMap((item, index) => {
+        const behind = array.slice(0, index);
+        const ahead = array.slice(index + 1);
+        return (
+          permutations([...behind, ...ahead])
+            .map(rest => [item, ...rest]));
+      });
+  }
+}
+
+function queryBoilerplate(index, query, options) {
+  const idToDoc = {};
 
   return {
-    rawResults,
-    fieldResults,
     idToDoc,
 
-    constitute: ids =>
+    constitute: (ids) =>
       ids.map(id => ({id, doc: idToDoc[id]})),
+
+    query: (query, options) => {
+      const rawResults =
+        index.search(query, options);
+
+      const fieldResults =
+        Object.fromEntries(
+          rawResults
+            .map(({field, result}) => [
+              field,
+              result.map(({id}) => id),
+            ]));
+
+      Object.assign(
+        idToDoc,
+        Object.fromEntries(
+          rawResults
+            .flatMap(({result}) => result)
+            .map(({id, doc}) => [id, doc])));
+
+      return {rawResults, fieldResults};
+    },
   };
 }