-
Notifications
You must be signed in to change notification settings - Fork 0
Search Engine
ABCrimson edited this page Mar 11, 2026
·
2 revisions
The built-in TypeScript scorer uses fuzzy matching with these scoring factors:
- Exact match — Highest score when query matches item value exactly
- Prefix match — High score for matches at the start of words
- Consecutive characters — Bonus for adjacent character matches
- Word boundary bonus — Higher scores when matches align with word boundaries (spaces, hyphens, camelCase)
- Position penalty — Matches earlier in the string score higher
Score aggregation uses Math.sumPrecise (ES2026) for accurate floating-point summation.
When the user types additional characters (e.g., "ap" → "app"), the engine only re-scores items that matched the previous query, using Set.difference for efficient candidate pruning.
// First search: scores all 10K items
engine.search('a', items); // → 6,000 results
// Incremental: only re-scores the 6,000 matches, not all 10K
engine.search('ap', items); // → 2,000 results (from 6K candidates)
engine.search('app', items); // → 500 results (from 2K candidates)Provide a custom scorer function:
import { createSearchEngine, type ScorerFn } from 'modern-cmdk';
const myScorer: ScorerFn = (query, item) => {
if (item.value.toLowerCase().includes(query.toLowerCase())) {
return { id: item.id, score: 1, matches: [] };
}
return null; // No match
};
using engine = createSearchEngine({ scorer: myScorer });For datasets > 10K items, use the WASM trigram index:
import { createWasmSearchEngine } from 'modern-cmdk-search-wasm';
await using engine = await createWasmSearchEngine();
engine.index(items);
const results = engine.search('query', items).toArray();See WASM Search for details.
| Operation | 1K Items | 10K Items | 100K Items |
|---|---|---|---|
| JS scorer (full pipeline) | ~0.5ms | ~5ms | ~50ms |
| JS scorer (incremental) | ~0.2ms | ~2ms | ~20ms |
| WASM scorer | ~0.1ms | ~0.8ms | ~3ms |