see all the JS alternatives with their sizes and feature sets and perf: https://github.com/leeoniya/uFuzzy (scroll to bottom)
i went down this path a few yrs ago and ended up picking ufuzzy: https://swyxkit.netlify.app/ufuzzy-search
you might be interested in doing a follow-up/update to your post, to use the .search() api, which does more stuff out of the box, such as outOfOrder, quoted, and negatives
Libsearch looks similar to uFuzzy (indexless regexp builder) but more simplistic. the other one i've seen that does this is sifter.js (predates uFuzzy, but i didnt discover it until researching libs to compare afterwards)
It’s a very clever RegEx engine, essentially. Though it’s unclear to me right now how will this library handles fuzzy search (e.g. Califnia instead of California) but it’s really cool to reason about its implementation
https://github.com/nextapps-de/flexsearch?tab=readme-ov-file...
I tried Fuse, lunr and MiniSearch, and I stayed with MiniSearch. Great flexibility and very good performance even when I am indexing almost a million documents + many useful features.
Also, I would also recommend giving FlexSearch a try, it has some fancy algorithm that supposedly makes searches extra fast https://github.com/nextapps-de/flexsearch?tab=readme-ov-file...
in my testing of fuzzy/substring matching it takes quite a while to create its huge index: https://github.com/leeoniya/uFuzzy?tab=readme-ov-file#perfor...
IndexedDB rows need to be very coarse grained, each operation with the IndexedDB API has very high overhead compared to something like walking a LSM tree in RocksDB or something. If the index does fit in memory, then the best move would be to store and load the entire index from a single or a few IndexedDB rows.
If you need to index a lot of documents in a way that doesn't fit in memory, I recommend you consider sqlite3, stored in either OPFS or on IndexedDB, and use sqlite's FTS5 full text search stuff for the index. There are several sqlite backends available (see https://github.com/rhashimoto/wa-sqlite/tree/master/src/exam...), something like their IDB VFS will store each block in the sqlite file as a row in IndexedDB essentially batching storage of the index rows into IDB rows for you (for more details read https://github.com/rhashimoto/wa-sqlite/blob/3c202615ed6f54e...)