Faceted Search & Aggregations
debt(d7/e5/b5/t7)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints explicitly state 'automated: no' and the code patterns (O(n) PHP loop for facet counts, unfiltered facet counts, multiple SQL GROUP BY queries) are not caught by standard linters. Tools listed (elasticsearch, meilisearch, algolia) are search engines, not static analysis tools. Misuse only becomes apparent through performance profiling or careful code review.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix describes migrating from multiple SQL GROUP BY queries to aggregations on filtered results in a search engine. This typically requires introducing or reconfiguring a search engine layer, updating query logic, and reworking how facet data is requested and rendered — spanning data access, business logic, and UI layers in at least one component.
Closest to 'persistent productivity tax' (b5). Faceted search applies to web and API contexts. A poor implementation (SQL-based facet counts) creates ongoing performance debt and a UX anti-pattern that affects every search interaction. It doesn't dominate the entire architecture but does persistently slow iteration on the search/filter experience and affects multiple stakeholders (backend, frontend, UX).
Closest to 'serious trap' (t7). The canonical misconception is that faceted search requires multiple database queries, leading developers to write N separate GROUP BY queries when a single search-engine aggregation handles all facets simultaneously. This directly contradicts how SQL aggregation intuition works elsewhere, and the mistake (unfiltered counts, O(n) queries) is both common and materially harmful to performance and UX.
Also Known As
TL;DR
Explanation
Faceted search computes the count of matching documents per category value as part of the search query, using the same filters applied to the main results. Elasticsearch aggregations, Meilisearch facets, and Typesense facets handle this natively. The SQL equivalent (multiple GROUP BY queries per facet dimension) is too slow. Facets enable exploratory search — users narrow results by clicking filter values whose counts show relevance.
Diagram
flowchart LR
RESULTS[Search results] --> FACETS[Facets - filter counts]
subgraph Facet Types
TERMS[Term facets<br/>category: PHP 42<br/>category: Security 38]
RANGE[Range facets<br/>difficulty: beginner 150<br/>difficulty: advanced 80]
DATE[Date histogram<br/>updated: this month 45]
end
USER[User selects PHP] --> FILTER[Filter: category=php]
FILTER --> REFINED[Refined results + updated counts]
INFO[Counts update dynamically<br/>based on current selection<br/>Elasticsearch aggregations]
style FACETS fill:#1f6feb,color:#fff
style REFINED fill:#238636,color:#fff
style INFO fill:#d29922,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Computing facet counts with separate SQL GROUP BY queries — O(n) queries for n facets; use a search engine.
- Not filtering facet counts by other selected filters — the facets should reflect the current filtered result set.
- Facet values not sorted by count — users expect most common values first.
- No 'show more' for facets with many values — showing all 500 brand values overwhelms users.
Code Examples
// Multiple SQL GROUP BY — O(n) queries, slow:
$results = $db->query('SELECT * FROM products WHERE category = ?', [$category]);
// Separate query per facet dimension:
$brandCounts = $db->query('SELECT brand, COUNT(*) FROM products WHERE category = ? GROUP BY brand', [$category]);
$priceCounts = $db->query('SELECT price_range, COUNT(*) FROM products ...');
// 5 facets = 6 queries — gets slower as facets are added
// Elasticsearch — one query returns results + all facet counts:
$query = [
'query' => ['term' => ['category' => $category]],
'aggs' => [
'brands' => ['terms' => ['field' => 'brand.keyword', 'size' => 10]],
'price_ranges' => ['range' => ['field' => 'price', 'ranges' => [
['to' => 50], ['from' => 50, 'to' => 100], ['from' => 100]
]]],
]
];
// Single query: 1000 results + brand counts + price range counts