Replacing fuzzy search with fuse.js

pull/483/head
Zef Hemel 2023-07-25 17:33:07 +02:00
parent 41fb82b9d2
commit 6510f06e0e
5 changed files with 75 additions and 7 deletions

View File

@ -57,7 +57,7 @@ export async function indexLinks({ name, tree }: IndexTreeEvent) {
delete pageMeta[key];
}
}
console.log("Extracted page meta data", pageMeta);
// console.log("Extracted page meta data", pageMeta);
await index.set(name, "meta:", pageMeta);
}

View File

@ -4,7 +4,7 @@ import { buildHandebarOptions } from "./util.ts";
import type { PageMeta } from "../../web/types.ts";
export async function queryComplete(completeEvent: CompleteEvent) {
const match = /#query ([\w\-_]+)*$/.exec(completeEvent.linePrefix);
const match = /#query ([\w\-_]*)$/.exec(completeEvent.linePrefix);
if (!match) {
return null;
}

View File

@ -9,11 +9,7 @@ import { FilterOption } from "../types.ts";
import { FunctionalComponent } from "https://esm.sh/v99/preact@10.11.3/src/index";
import { FeatherProps } from "https://esm.sh/v99/preact-feather@4.2.1/dist/types";
import { MiniEditor } from "./mini_editor.tsx";
import { fuzzySearchAndSort } from "./fuzzy_search.ts";
type FilterResult = FilterOption & {
result?: any;
};
import { fuzzySearchAndSort } from "./fuse_search.ts";
export function FilterList({
placeholder,

View File

@ -0,0 +1,25 @@
import { FilterOption } from "../types.ts";
import { assertEquals } from "../../test_deps.ts";
import { fuzzySearchAndSort } from "./fuse_search.ts";
Deno.test("testFuzzyFilter", () => {
const array: FilterOption[] = [
{ name: "My Company/Hank", orderId: 2 },
{ name: "My Company/Hane", orderId: 1 },
{ name: "My Company/Steve Co" },
{ name: "Other/Steve" },
{ name: "Steve" },
];
// Prioritize match in last path part
let results = fuzzySearchAndSort(array, "");
assertEquals(results.length, array.length);
results = fuzzySearchAndSort(array, "Steve");
assertEquals(results.length, 3);
results = fuzzySearchAndSort(array, "Co");
// Match in last path part
assertEquals(results[0].name, "My Company/Steve Co");
// Due to orderId
assertEquals(results[1].name, "My Company/Hane");
assertEquals(results[2].name, "My Company/Hank");
});

View File

@ -0,0 +1,47 @@
// @deno-types="https://deno.land/x/fuse@v6.4.1/dist/fuse.d.ts"
import Fuse from "https://deno.land/x/fuse@v6.4.1/dist/fuse.esm.min.js";
import { FilterOption } from "../types.ts";
type FuseOption = FilterOption & {
baseName: string;
};
export const fuzzySearchAndSort = (
arr: FilterOption[],
searchPhrase: string,
): FilterOption[] => {
if (!searchPhrase) {
return arr.sort((a, b) => (a.orderId || 0) - (b.orderId || 0));
}
const enrichedArr: FuseOption[] = arr.map((item) => {
return { ...item, baseName: item.name.split("/").pop()! };
});
const fuse = new Fuse(enrichedArr, {
keys: [{
name: "name",
weight: 0.3,
}, {
name: "baseName",
weight: 0.7,
}],
includeScore: true,
shouldSort: true,
isCaseSensitive: false,
threshold: 0.6,
sortFn: (a, b): number => {
// console.log(a, b);
if (a.score === b.score) {
const aOrder = enrichedArr[a.idx].orderId || 0;
const bOrder = enrichedArr[b.idx].orderId || 0;
if (aOrder !== bOrder) {
return aOrder - bOrder;
}
}
return a.score - b.score;
},
});
const results = fuse.search(searchPhrase);
// console.log("results", results);
return results.map((r) => r.item);
};