How to Implement Autocomplete Suggestions While Preserving Scoring Accuracy in FlexSearch
Enable { suggest: true } in your search options to activate FlexSearch's fallback suggestion mode, which only triggers after exact matching fails and preserves the original relevance scoring algorithm for all returned results.
FlexSearch is a high-performance full-text search library that balances speed with relevance. When building autocomplete functionality, developers often worry that enabling suggestions will compromise the accuracy of result ranking. The library's suggestion mode is specifically designed to preserve scoring accuracy by only activating as a fallback mechanism when exact queries return no matches, ensuring that your autocomplete suggestions maintain the same relevance ordering as standard searches.
How Suggestion Mode Works in FlexSearch
The suggestion functionality lives in src/index/search.js and operates as a lightweight fallback rather than an alternative search path. When you pass { suggest: true } to the search method, FlexSearch first executes a normal strict search. Only if that search returns zero results does the engine enter suggestion mode.
The Fallback Trigger Mechanism
The suggestion flag is read from the options object at the beginning of the search execution:
suggest = SUPPORT_SUGGESTION && options.suggest;
According to the source code in src/index/search.js (lines 68-71), this boolean determines whether the engine can enter fallback mode. When a multi-term query finishes without any hits, FlexSearch detects this condition at lines 75-84 and enters a fallback loop that resets the resolution and keyword before restarting the term iteration. This design ensures that the normal relevance scoring—including term frequency, resolution handling, and context awareness—is fully applied to the original query before any fallback occurs.
Resolution and Context Preservation
The scoring accuracy is maintained through careful state management during the fallback transition:
-
Resolution handling: During normal search, the engine uses
this.resolution(orresolution_ctxfor contextual searches) to determine how many top-ranked documents to retain per term (lines 30-34). When the fallback triggers, the resolution is reset tothis.resolution(lines 77-79), ensuring the same ranking thresholds apply to suggestion results. -
Context management: In normal operation, the context keyword advances only when a term produces results (lines 14-22, 65-72). During fallback, the context is cleared (
keyword = "") so the engine can search without context constraints, but this only happens after all normal attempts have been exhausted. -
Scoring consistency: Whether returning exact matches or suggestions, the final results pass through the same
intersect()function (found insrc/intersect.js) which applies the resolution-based scoring algorithm. The fallback re-runs this identical logic on newly gathered results, ensuring no degradation in ranking quality.
Implementing Autocomplete with Accurate Scoring
To implement autocomplete suggestions while preserving FlexSearch's relevance scoring, initialize your index with appropriate tokenization and enable the suggestion flag only when needed.
Basic Index Configuration
Create an index with strict tokenization and context support, then enable suggestions for fallback queries:
import FlexSearch from "flexsearch";
const index = new FlexSearch.Index({
tokenize: "strict", // exact tokenization
resolution: 10, // keep top-10 matches per term
context: { depth: 3, bidirectional: true } // optional context support
});
// Add documents (id → content)
index.add(0, "1 2 3 2 4 1 5 3");
index.add(1, "zero one two three four five six seven eight nine ten");
index.add(2, "four two zero one three ten five seven eight six nine");
// Strict search returns empty array when no exact match exists
console.log(index.search("1 3 4 7")); // → []
// Suggestion mode returns the most relevant document
console.log(index.search("1 3 4 7", { suggest: true })); // → [0]
In this example, the engine first attempts a strict search for the exact terms "1", "3", "4", and "7". Finding no document containing all terms, it falls back to suggestion mode and returns document 0 because it contains the highest frequency of the individual query terms, preserving the relevance scoring that ranked it highest.
UI Integration with Ranked Results
When building an autocomplete interface, use the resolve option to receive a plain array of document IDs ordered by relevance:
function onInputChange(term) {
// Request up to 5 suggestions maintaining relevance order
const suggestions = index.search(term, {
suggest: true, // enable fallback suggestions
limit: 5, // cap number of returned IDs
resolve: true // return plain array, not a Resolver object
});
// suggestions is an ordered list of document IDs
renderAutocomplete(suggestions);
}
Setting resolve: true ensures FlexSearch returns the ranked array directly from the resolve_default function in src/resolve/default.js, allowing your UI to display suggestions ordered by the same scoring algorithm used for exact matches.
Retrieving Scores with Document Enrichment
To access the actual relevance scores alongside document IDs, use the enrich option:
const records = {
0: { title: "First", content: "1 2 3 2 4 1 5 3" },
1: { title: "Second", content: "zero one two three four five six seven eight nine ten" },
2: { title: "Third", content: "four two zero one three ten five seven eight six nine" }
};
function searchWithDetails(query) {
// enrich: true returns [{ id, doc, score }]
const results = index.search(query, { suggest: true, enrich: true });
// Attach original document data while preserving score
return results.map(r => ({
...r,
record: records[r.id]
}));
}
The suggestion fallback still executes the final intersect() step, which computes a score for each hit based on term frequency and resolution settings. By enabling enrich, you receive this score metadata alongside the document ID, giving you full visibility into how FlexSearch ranked your autocomplete suggestions.
Key Source Files for Scoring Accuracy
Understanding these core files helps verify that suggestion mode preserves scoring accuracy:
-
src/index/search.js: Contains the core search implementation including the suggestion fallback logic (lines 75-84), resolution handling, and the conditional that checksif (suggest && keyword && (index === length - 1))before entering fallback mode. -
src/intersect.js: Implements the intersection and scoring algorithm applied to multi-term results. This same function processes results whether they come from exact matching or suggestion fallback. -
src/config.js: Defines theSUPPORT_SUGGESTIONfeature toggle that enables the suggestion functionality at build time. -
src/resolve/default.js: Houses theresolve_defaultfunction that produces the final ranked array, used consistently after both normal searches and suggestion fallbacks. -
test/scoring.js: Contains the test suite verifying that scoring behavior remains consistent when suggestion mode is active.
Summary
-
Suggestion mode is a fallback: FlexSearch only activates
suggest: trueafter the normal search path returns zero results, ensuring exact matches always receive priority ranking. -
Scoring algorithm remains unchanged: The same
intersect()function and resolution-based scoring apply to both exact matches and suggestions, as implemented insrc/index/search.js. -
Context and resolution are reset, not modified: When falling back, the engine clears context (
keyword = "") and resets resolution tothis.resolution, but uses the identical scoring pipeline to rank results. -
Enrich option exposes scores: Use
{ enrich: true }to access relevance scores even when using suggestion mode, confirming that ranking accuracy is preserved.
Frequently Asked Questions
Does enabling suggestion mode slow down normal searches?
No. The suggestion flag is checked only after the normal search completes without results. According to src/index/search.js, the condition if (suggest && keyword && (index === length - 1)) is evaluated only when the term iteration finishes with no hits. Normal searches that return matches never enter the fallback loop, so performance characteristics remain identical for exact match queries.
How does FlexSearch handle context when falling back to suggestions?
When the fallback triggers, the engine clears the context keyword by setting keyword = "" (visible in src/index/search.js lines 77-79). This allows the search to proceed without context constraints, effectively broadening the query to find partial matches. However, this only occurs after all contextual search attempts have failed, ensuring that context-aware exact matches maintain their priority in the results.
What is the difference between suggestion mode and fuzzy matching?
Suggestion mode ({ suggest: true }) operates at the query execution level by relaxing the requirement that all terms must match, instead returning documents that contain the best subset of terms. Fuzzy matching operates at the index level, allowing character-level variations in individual terms. You can combine both approaches, but suggestion mode specifically preserves scoring accuracy by reusing the standard intersection algorithm while fuzzy matching uses edit-distance calculations in the index.
Can I customize the scoring algorithm when using autocomplete suggestions?
The scoring algorithm is fixed in the intersect() function located in src/intersect.js, which applies resolution-based ranking to all results regardless of whether they come from exact matching or suggestion fallback. While you cannot override the internal scoring without modifying the source, you can use the enrich option to retrieve raw scores and implement additional ranking layers in your application logic based on business requirements.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →