3.5 KiB
3.5 KiB
name, description
| name | description |
|---|---|
| sp-search | Full-text and fuzzy search primitives with in-memory BM25 engine, trigram fuzzy matching, faceted search, and pagination support. |
Architecture
| Component | Responsibility |
|---|---|
createMemorySearchEngine / MemorySearchEngine |
In-memory BM25 search engine with indexing, search, faceting, and pagination |
tokenize / normalizeToken / simpleStem |
Text tokenization pipeline with stemming and normalisation |
buildTrigrams / trigramSimilarity |
Trigram-based fuzzy string similarity scoring |
bm25Score / computeIdf / tfIdfScore |
BM25 and TF-IDF scoring functions for relevance ranking |
SEARCH_CODES + SearchError |
Structured error registry for query validation and engine failures |
FieldConfigSchema / SearchQuerySchema / PaginationSpecSchema |
Zod schemas for all query and configuration types |
File Structure
packages/persistence/search/search/src/
engine/memory-engine/ MemorySearchEngine and createMemorySearchEngine
text/tokenizer/ tokenize, normalizeToken, simpleStem
text/trigram/ buildTrigrams, trigramSimilarity
text/scorer/ bm25Score, computeIdf, tfIdfScore
errors/ SearchError and SEARCH_CODES
schemas/ Zod schemas for queries, filters, pagination, fields
types/ TypeScript interfaces (SearchDocument, SearchHit, FacetBucket, etc.)
constants/ BM25_B, BM25_K1, DEFAULT_FUZZY_THRESHOLD, DEFAULT_PAGE_SIZE
Sibling packages
@suaveplan/pagination— pagination primitives consumed by search results@suaveplan/error— structured error registry viadefineCodes@suaveplan/types— shared TypeScript primitives@suaveplan/testing— unit test infrastructure
Patterns
Quick Start
import { createMemorySearchEngine } from "@suaveplan/search";
interface Product { id: string; name: string; price: number }
const engine = createMemorySearchEngine<Product>({
fields: [
{ name: "name", type: "text", searchable: true },
{ name: "price", type: "number", sortable: true },
],
});
await engine.index([
{ id: "1", name: "Laptop Pro", price: 999 },
{ id: "2", name: "Laptop Air", price: 799 },
]);
const result = await engine.search({ text: "laptop" });
console.log(result.hits.length); // 2
Fuzzy matching with trigrams
import { trigramSimilarity, buildTrigrams } from "@suaveplan/search/text/trigram/trigram";
const score = trigramSimilarity("colour", "color");
BM25 scoring
import { bm25Score, computeIdf } from "@suaveplan/search/text/scorer/scorer";
const idf = computeIdf(totalDocs, docsContainingTerm);
const score = bm25Score({ tf: 3, docLength: 100, avgDocLength: 80, idf });
Constraints
- In-memory only; no persistent backing store
- BM25 parameters
BM25_K1andBM25_Bare exported constants (default 1.2 and 0.75) - Fuzzy threshold defaults to
DEFAULT_FUZZY_THRESHOLD; override via search options - Pagination uses
@suaveplan/paginationprimitives - OTel instrumentation via
@opentelemetry/api(no-op when no SDK registered)
Checklist
- Verify
MemorySearchEnginesupports text, number, and boolean field types - Confirm
SEARCH_CODESregistered viadefineCodes("SEARCH", [...]) - Check subpath exports in
package.jsonalign withsrc/modules - Run
bunx turbo lint typecheck test build --filter=@suaveplan/search - Confirm benchmarks in
src/__benchmarks__/execute without error