Curiosity

Full Text Search

Full-text (BM25) search is the default retrieval path. Configuration boils down to three questions: which fields are indexed, how they rank, and what counts as "the same" word.

1. Pick the searchable fields

  1. Settings → Search → Full Text Search.
  2. + Add more — pick (node type, field) pairs.
  3. Toggle Searchable on the node type to control whether matches surface in the default workspace search results.

Recommended fields per type:

Type Typical fields Notes
SupportCase Summary, Content Boost Summary higher; Content is longer-tailed.
KbArticle Title, Body, Tags Title and Tags should outweigh Body.
Product Name, Description, Sku Sku boosted heavily — exact matches are intent signals.

Avoid indexing high-cardinality opaque fields (UUIDs, hashes) — they bloat the index without helping recall.

2. Adjust ranking with field boosts

Each indexed field has a boost value (the + / controls). Matches in higher-boost fields score higher. Useful defaults:

  • Title-like fields: 3–5×
  • Summary fields:
  • Body fields: (baseline)
  • Tags / labels: 2–3×

Adjust iteratively against the evaluation framework — don't tune by gut.

3. Synonyms

Domain abbreviations and aliases hurt recall when they're not normalized. Add them under Settings → Search → Predefined Synonyms:

mbp, MacBook Pro
ssd, solid-state drive
ram, memory

Synonyms are bi-directional — a query for mbp finds documents containing MacBook Pro and vice versa.

Multi-language behavior

Each indexed field is tied to its node's language detection (via the NLP pipeline). The search engine stems, lower-cases, and removes stop-words per-language. For mixed-language corpora, no extra setup is needed — each document is processed with its detected language.

From code

The same configuration drives SearchRequest from custom endpoints:

var req = SearchRequest.For("battery drain");
req.BeforeTypesFacet = new HashSet<string> { "SupportCase" };

// Optional: limit to a subset of indexed fields for this query.
req.RestrictedFields = new[] { "Summary" };

var query = await Graph.CreateSearchAsUserAsync(req, CurrentUser, CancellationToken);
return query.Take(20).Emit();

Setting RestrictedFields on a request narrows ranking to a slice of the configured index — useful when you want a "title-only" search lane from the same index.

Validating changes

After changing field boosts or synonyms:

  1. Run the evaluation framework eval set. Look for regressions in recall@k and MRR.
  2. Spot-check a handful of representative queries from production logs.
  3. If you've added a new indexed field, rebuild the index: Settings → Search Index → Rebuild.
© 2026 Curiosity. All rights reserved.