Fuzzy Search
Fuse.js uses a modified Bitap algorithm for approximate string matching. It finds strings that are approximately equal to a given pattern — tolerating typos, transpositions, and missing characters.
const fuse = new Fuse(['apple', 'banana', 'orange'], {
includeScore: true
})
fuse.search('aple')
// [{ item: 'apple', refIndex: 0, score: 0.25 }]
How It Works
The Bitap algorithm computes the edit distance between the search pattern and each position in the text. The implementation uses bitwise operations for speed, with a pattern length limit of 32 characters per search term.
The algorithm produces a fuzziness score between 0 and 1:
0— perfect match1— complete mismatch
This score is then combined with key weight and field-length norm to produce the final relevance score.
TIP
See How Fuzzy Search Works for an interactive walkthrough of edit distance.
Controlling Fuzziness
Three options work together to determine what counts as a match:
threshold
- Default:
0.6
The cutoff for the fuzziness score. A threshold of 0.0 requires a perfect match. A threshold of 1.0 matches anything.
// Strict matching
const fuse = new Fuse(list, { keys: ['title'], threshold: 0.2 })
// Permissive matching
const fuse = new Fuse(list, { keys: ['title'], threshold: 0.8 })
location
- Default:
0
The expected position of the pattern in the text. The algorithm penalizes matches that are far from this position.
distance
- Default:
100
How far from location a match can be before being penalized to the point of exclusion. The effective search window is:
threshold × distance = maximum offset from location
With defaults (threshold: 0.6, distance: 100), the pattern must appear within 60 characters of position 0 to match. For example, searching for "zero" in "Fuse.js is a powerful, lightweight fuzzy-search library, with zero dependencies" would not match — "zero" appears at index 62, just outside the window.
ignoreLocation
- Default:
false
When true, disables location-based scoring entirely. The pattern can appear anywhere in the text and still match. This is useful when you don't know or care where the match might be.
const fuse = new Fuse(list, {
keys: ['description'],
ignoreLocation: true
})
TIP
The default options effectively search only the first ~60 characters of each field. If your data has long text fields, either increase distance, or set ignoreLocation: true.
Try adjusting threshold, location, and distance below to see how they interact.
Effective window: characters 0 to 50 (51 chars). A match 60 characters from position 0 would be at the threshold cutoff.
Note: distance also affects scoring — a larger distance means less penalty per character of offset, so the same match gets a better score.
Other Options
isCaseSensitive
- Default:
false
When true, comparisons are case-sensitive.
ignoreDiacritics
- Default:
false
When true, comparisons ignore diacritics (accents). For example, é matches e.
findAllMatches
- Default:
false
When true, the algorithm continues searching to the end of the text even after finding a perfect match. Useful when you need all match indices for highlighting.
minMatchCharLength
- Default:
1
Only return matches whose length exceeds this value. Set to 2 to ignore single-character matches.
Scoring
The final relevance score for a result combines three factors:
- Fuzziness score — the raw Bitap score described above
- Key weight — optional per-key
weight(defaults to1). Higher weight = more influence on ranking. Weights are normalized internally. - Field-length norm — shorter fields rank higher. A match in a title is more significant than the same match in a long description.
Scores range from 0 (perfect match) to 1 (complete mismatch). Enable with includeScore: true.
ignoreFieldNorm
- Default:
false
When true, field length has no effect on scoring. Useful when you only care whether a term exists, not how prominent it is.
fieldNormWeight
- Default:
1
Adjusts the strength of the field-length norm. 0 is equivalent to ignoring it. 0.5 reduces the effect. 2.0 amplifies it.
