← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

Faceted Search & Aggregations

Search Intermediate
debt(d7/e5/b5/t7)
d7 Detectability Operational debt — how invisible misuse is to your safety net

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.

e5 Effort Remediation debt — work required to fix once spotted

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.

b5 Burden Structural debt — long-term weight of choosing wrong

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).

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

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.

About DEBT scoring →

Also Known As

facets aggregations filters faceted navigation

TL;DR

Dynamically computed counts for filter categories based on current results — the 'Brand (42) | Price $0-50 (18)' sidebar that refines search results.

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

Faceted search requires multiple database queries — search engines compute all facet counts in a single query; doing it in SQL with multiple GROUP BY queries is N times slower.

Why It Matters

Faceted search dramatically improves discoverability — showing 'no results' for a filter vs showing the count before clicking prevents dead-end searches.

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

✗ Vulnerable
// 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
✓ Fixed
// 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

Added 15 Mar 2026
Edited 22 Mar 2026
Views 53
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 1 ping W 2 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 1 ping F 2 pings S 2 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 1 ping M 0 pings T 1 ping W 0 pings T 0 pings F 0 pings S 1 ping S 1 ping M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 9 Perplexity 6 SEMrush 5 Scrapy 5 Ahrefs 4 Google 3 Majestic 2 Unknown AI 2 ChatGPT 2 Claude 1 Bing 1 Meta AI 1 PetalBot 1
crawler 39 crawler_json 3
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: High
⚡ Quick Fix
Build facets from aggregations on filtered results — each facet shows counts for the current filtered view, not the total index, so users understand exactly what's available within their current selection
📦 Applies To
any web api
🔗 Prerequisites
🔍 Detection Hints
Filter without dynamic facet counts; facets showing total counts not filtered counts; O(n) PHP loop to compute facet counts from results
Auto-detectable: ✗ No elasticsearch meilisearch algolia
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: Medium ✗ Manual fix Fix: High Context: File Tests: Update


✓ schema.org compliant