Skip to content

Faceted Search and Filters That Don’t Return Zero Results

6 min read · updated August 3, 2026

A faceted interface makes a promise: every filter you can click leads somewhere. Breaking that promise is the single most common way a good search engine feels broken, and it happens for a reason that is pure arithmetic.

What a facet count actually is

The number next to “Brand: Acme (34)” is not a property of the catalogue. It is the size of the intersection of the current result set with that facet value — computed per query, over the full result set, not the page you are showing. That distinction matters because it is where the cost is: paging is cheap, counting is not.

Mechanically, engines compute this as a set intersection over posting lists, usually with bitmaps. A roaring bitmap per facet value, ANDed against the bitmap of the current result set, gives the count in a cardinality operation rather than a scan. This is why facet counts are fast on an inverted index and awkward on a pure vector index, where there is no posting list to intersect — one of several reasons hybrid architectures exist, discussed in pre-filtering versus post-filtering.

There is a semantic decision buried here too. Within a single facet, selecting two values almost always means OR — a shopper who ticks red and blue wants both. Across facets it means AND. Engines that get this backwards produce counts that do not add up to anything the user can reconcile, and it is the first thing to check when the numbers look wrong.

There is a consequence of that asymmetry which trips up nearly every first implementation. If facet values within a facet are OR-ed, then the counts shown for that facet must be computed against a result set that has not had that facet applied — otherwise ticking “red” makes every other colour show zero, and the interface claims the shop sells nothing blue. So each facet needs its counts computed against the intersection of all the other facets, and an engine that supports faceting properly does this for you under a name like “facet filters” or “post filters”. Doing it by hand means one query per facet, which is where the cost comes from.

Hierarchical facets — category, subcategory, leaf — add one more rule. Counts at a parent level must include everything beneath it, or the numbers do not add up as the user drills down and they stop trusting any of them. Store the full path as a set of tokens on each document rather than only the leaf, so the parent count is an ordinary intersection rather than a recursive walk.

Why zero results are inevitable

Model each filter by its selectivity p_i: the fraction of the corpus it keeps. If the filters were independent, the expected size of the result set after applying all of them is:

E[results] = N * PRODUCT of p_i

N = 50,000 products
p = 0.20 (category)  0.15 (brand)  0.30 (colour)  0.10 (price band)

  0.20 * 0.15 = 0.0300
       * 0.30 = 0.0090
       * 0.10 = 0.0009

E[results] = 50,000 * 0.0009 = 45

Four filters and 50,000 products leaves 45. Add a fifth at selectivity 0.05 and the expectation is 2.25. A sixth and it is a fraction of a document — which is to say, most of the time, zero.

And independence is the optimistic case. Real filters are correlated, often negatively: the intersection of a niche brand and an unusual size is smaller than the product of their selectivities, because that brand does not stock that size. So the true curve falls faster than this one. The conclusion is not that you should have fewer facets. It is that a user with five filters applied is a normal user, and the interface must be built for them rather than treating their empty page as an edge case.

Prevention beats recovery

There is one design rule that removes most of the problem, and it is the rule that facet counts must be computed against the current result set, and any value whose count is zero must not be clickable. Do that and a dead end becomes structurally unreachable: a user cannot navigate to an empty result set, because the click that would take them there was never offered.

It costs something. Counts must be recomputed on every filter change, which is the expensive part of the query, and it means the facet list shrinks as the user narrows — which some product owners dislike because it looks like options are disappearing. They are disappearing; they were never real. Greying out with a visible zero is the compromise that keeps the option list stable and still tells the truth.

The one case this rule does not cover is a free-text query combined with filters, because the query itself can produce zero before any filter applies. That is a different failure, and it belongs to zero-result and long-tail handling.

The recovery ladder

When you land on zero anyway — from a bookmarked URL, a stale link, a restocking change between page loads — recover in this order. Each rung keeps more of the user’s stated intent than the one below it.

  • Name what emptied it. Compute the result count with each single filter removed. Whichever removal recovers the most results is the one to offer first, as a specific action: “remove size 14 to see 62 results”, not “try broadening your search”.
  • Relax the narrowest numeric constraint. Price and date ranges expand naturally. Widening a price band by 20% and saying so is almost always better than dropping it.
  • Convert the least-informative filter to a boost. Colour is usually a preference, not a requirement. Ranking red items first over a set that includes other colours is closer to what the user meant than an empty page.
  • Fall back to the query alone, filters shown as restorable chips. The user can put back the one they actually cared about.
  • Then, and only then, show alternatives — related categories, similar items, back-in-stock notification. This is the last rung because it abandons the stated intent, and putting it first is the pattern that makes people think the site is guessing.

Instrument the ladder. The rate at which each rung fires is a direct measurement of which part of your catalogue or your facet design is failing, and it is one of the few search metrics that points at a fix rather than at a number.

Faceted Search and Filters That Don’t Return Zero Results · Multigrid