Filters and Facets
Facets are the structured-data sidekicks of free-text search — checkboxes, sliders, and date ranges that let the user narrow results without re-typing a query. Curiosity supports three facet shapes, each with a different cost/value trade-off.
Property facets
Driven by a property directly on the node. Best for low-cardinality, normalized fields:
| Property example | Good facet? | Why |
|---|---|---|
SupportCase.Status |
Yes | Small set ("Open", "Pending", "Resolved"). |
Article.Category |
Yes | Curated, small set. |
SupportCase.Summary |
No | Unique per row — facet would explode. |
Article.Updated |
Use time facet | Use the time filter instead. |
Configure under Settings → Search → Property Facets. The workspace auto-generates checkbox or sort-by-count UI from there.
Related (graph) facets
The differentiator versus most search engines. A related facet filters by an edge to a normalized entity node — e.g. "cases for devices made by Apple".
Two reasons to use related facets instead of duplicating the field on the node:
- No denormalization. If a device changes manufacturer, all cases follow automatically.
- Multi-hop. Filter on something two or three edges away (manufacturer of the device of the case).
Configure under Settings → Search → Related Facets.
From code:
var req = SearchRequest.For("screen flicker");
req.BeforeTypesFacet = new HashSet<string> { "SupportCase" };
req.RelatedFacets = new Dictionary<string, List<RelatedFacet>>
{
["Manufacturer"] = new()
{
new RelatedFacet { TargetType = "Manufacturer", TargetKey = "Apple" }
}
};
var query = await Graph.CreateSearchAsUserAsync(req, CurrentUser, CancellationToken);
return query.Emit();
Time filter
Every node carries a Timestamp (or Time) field. The workspace exposes a global time filter (week, month, custom range) that applies to any indexed node type.
Exclude reference types from the time filter — Manufacturer, Status, Category rarely change and would show up in every time window:
- Settings → Search → Time Filter Exclusions
Value facets
Driven by a numeric range — score buckets, age ranges, prices. Configured the same way as property facets but rendered as a range slider.
Performance tips
- Cardinality matters. Facets over millions of distinct values become slow to count. Pre-aggregate by binning if necessary.
- Pre-compute multi-hop facets. If a related facet walks three hops, consider materializing the relationship onto the source node during ingestion so the facet is one hop.
- Lazy load facet values. The UI defaults to top-N values per facet. Don't expose
Show allfor high-cardinality facets in production.
Cross-links
- Full text search
- Ranking and boosting
- Search execution scopes — for code-driven custom facets.
- Schema design — modeling for facet-friendliness.