Lightweight, dependency-free index search with SSR support
โ ๏ธ Work in progress. Things are most certainly incomplete and/or broken, and will definitely change.
- ๐โโ๏ธ Simple and efficient for when you need just a little bit more than
Array.filter()
- ๐ฆ Supports SSR with client side hydration
- ๐ Customizable tokenization/normalization/search/etc. handlers
- ๐ Tiny (<1kb min+gzip) footprint with no runtime dependencies
- ๐ฆ Use everywhere: works with Deno, Node.js, and in the browser
From a CDN:
import createSearch from "https://esm.sh/gh/andreasphil/js-inverted-index@<tag>";
With a package manager:
npm i github:andreasphil/js-inverted-index#<tag>
This package implements a simple
inverted index for string
s or
stringified data, called documents. To get started, initialize the index and
tell it which properties should be indexed:
const data = [
{ id: 1, title: "Terror, The", director: { name: "Noella Grassot" } },
{ id: 2, title: "Tortured", director: { name: "Carlotta Hembry" } },
{
id: 3,
title: "Early Summer (Bakushรป)",
director: { name: "Zaneta Flaubert" },
},
];
const { search, add } = createSearch({
fields: ["title", "director.name"],
});
createSearch
returns an object with functions for interacting with the index:
add(data);
search("germany"); // -> [{ id: 1 /*...*/ }, { id: 2 /*...*/ }]
In the default configuration, indexing splits the fields into words by matching
the \w+
regex, discards everything else, and converts the result to lowercase.
Each obtained token is saved as a key in the index, with a list of the id
s of
the matching documents as the values. Documents added to the index are saved too
and will be returned as the search results.
Once built, the search index can be saved and restored. This can be useful, for example, if you want to generate the index on the server, and send the complete index instead of computing it in the client.
// Server
const { search, add, dump } = createSearch({
/* Options */
});
add(yourDocuments);
const serializedIndex = JSON.stringify(dump);
// Client
const { search, hydrate } = createSearch({
/* Options */
});
hydrate(JSON.parse(serializedIndex), yourDocuments); // Documents won't be included in the dump
search("query"); // Use as usual
By providing the corresponding callbacks to the index during initialization, you can customize:
- how IDs are extracted from documents,
- how values are split into tokens,
- how tokens are normalized, and
- how search results are determined.
See the IndexingOptions
type in lib.js for all the required
typings, and createSearch
for an example with the default configuration.
This library is built with esbuild. Packages are managed by pnpm. Tests are powered by Node.js' test runner. The following commands are available:
pnpm test # Run tests once
pnpm test:watch # Run tests in watch mode
pnpm build # Typecheck, emit declarations and bundle