Show HN: Frontend Fuzzy Search (github.com)
I have spent several years working on search engines in the backend and have now utilized that experience to develop a fuzzy search library for the frontend. It's fast, accurate and can be used for all languages. It should be easy to integrate into your Javascript / Typescript projects. If you test it and find any edge cases that did not work for you please let me know.
The implementation is based on 3-grams by the book, augmented with a novel trick of sorting the characters within the 3-grams for enhanced accuracy. For a detailed explanation you may refer to my related blog post at https://www.m31coding.com/blog/fuzzy-search.html.
Happy Coding!
37 comments
[ 5.3 ms ] story [ 84.6 ms ] threadI’m curious if there’s a tl;dr on how this is better or different to Fuse, which is a very popular established client side fuzzy searching library.
https://github.com/krisk/fuse
Distance definitions such as the Levenshtein and Damerau-Levenshtein distances provide a solid basis for discussions on accuracy. However, they are costly to compute and hence not widely adopted in fuzzy search libraries.
I started by using the known filter equation for the Levenshtein distance and computed a quality score with a leightweight formula. Then, I realized that the filter equation can be extended to the Damerau-Levenshtein distance by sorting the characters of the 3-grams.
In my tests, this implementation worked well. Please let me know how it works for you if you test it.
I'd say a search is accurate if it finds what most closely matches the query, for some definition of "matches". A search is useful if most people can find what they are looking for on the first try.
That is, a search being accurate doesn't necessarily translate to usefulness, if people don't (or can't) know how to write those accurate queries.
I'd imagine this is why fuzzy searches exist. Fuzzier queries allow for a larger spectrum of possible matches, which means a larger set of queries can turn up those results someone is looking for. Queries do not have to be as precise, and writing useful queries is easier.
But to me it seems diametrically opposed to accuracy. Usefulness is a much more intuitive measure, because the query does not have to be perfectly accurate in order to find the right result.
Alternatively, you could focus on the quality of ranking of the returned matches: how often the correct result is near the top (and how near) when the user finds what they are looking for. Ideally you want this as high as possible.
So, in the end, I believe it's worthwhile to try different implementations and share our subjective experiences.
Context: Say I have a bunch of blog posts from which I create an inverted index at "export to html" time, in order to avoid indexing the blog content at runtime on every page visit. Is there a way to persist the internal state of the fuzzy search across different page requests (e.g, /blog-post-1, /blog-post-2), so it only builds its internal state/index once?
The pre-generated inverted index could be quite large and I would like to avoid parsing it on every page request.
I am not sure what you mean by "store it in an index db", but I was thinking about using the searcher on a static website (no real backend, only a fileserver serving pre-generated html files). So if I understand you correctly, in order for this to work I would have to cache Memento via a local storage and load it on every page load/search request.
Unfortunately the index would change over time, thus one would have to detect this somehow and regenerate Memento as well.
As a bonus you could cache the memento in the local storage or session storage.
http://elasticlunr.com/
I have always been a bit unsure when to reach for client-side code for festures like search, filtering, and pagination though. The features are powerful for sure and if the site is otherwise static I can see some value there, but it means having to ship all searchable data to the browser. It feels like an easy security risk to avoid, and offloading that work to a backend where the state lives feels more straightforward (as long as you have a hosted backend at all).
It’s not nearly as good a fuzzy search as this is as I just kinda tinkered with it till it felt ok for the purpose but it could be way better.
Source: https://github.com/trescenzi/brainstorm Site: https://brainstorm.tcrez.xyz/
Most importantly very few fuzzy search libs can get a simple substring match as a priority, which is understandable but not helpful. Imagine searching for “xample” and not having “example” among the results.
[1] https://duckdb.org/2023/12/18/duckdb-extensions-in-wasm.html
Keep up the great work!
i will add it to the uFuzzy benchmarks :)