How does filtered and hybrid search change what HNSW has to do?
Filtered and hybrid search change what HNSW has to do by adding a second requirement on top of pure vector similarity — a query no longer just asks for the nearest neighbors, it asks for the nearest neighbors that also satisfy some separate condition, and satisfying both requirements together turns out to be considerably harder than either one on its own.
Why does naively filtering results after a search lose recall?
The simplest approach runs an ordinary, unfiltered HNSW search first, then discards any results that don’t satisfy the filter afterward. This works fine when the filter accepts most of the dataset, but it degrades badly as the filter becomes more selective: if only a small fraction of the dataset satisfies the filter, an ordinary search’s top candidates might contain few or none of the vectors that would actually pass it, leaving a search that returns far fewer usable results than requested, or results considerably worse than the true best matches among the vectors that do satisfy the filter. The underlying problem is that the search never knew about the filter while it was running, so it had no reason to steer toward the parts of the graph where filter-satisfying vectors actually live.
Why isn’t filtering before the search a clean solution either?
The opposite approach — identifying every vector that satisfies the filter first, then searching only among those — avoids the recall problem above, but introduces a different cost. For a highly selective filter matching only a tiny fraction of the dataset, this can mean falling back to comparing the query against every filter-satisfying vector directly, since a subset small enough might not justify the overhead of graph traversal at all. For a moderately selective filter, building and searching a temporary structure over just the filtered subset for every single query can itself become expensive if that has to happen fresh each time rather than being precomputed. Whether pre-filtering or post-filtering wins out in a given situation depends heavily on filter selectivity — how large a fraction of the dataset the filter actually accepts — and on how well vector similarity happens to correlate with whatever property the filter is based on, since a filter that correlates strongly with regions of the vector space behaves very differently than one that cuts across the space in a way unrelated to embedding similarity.
What does an allow-list-based, filter-aware traversal actually do differently?
A more integrated approach keeps the graph traversal itself running normally — following every edge exactly as an ordinary search would — but tracks separately which candidates encountered along the way actually satisfy the filter, only adding filter-satisfying candidates to the final result set while still allowing the search to pass through non-satisfying nodes purely as intermediate stepping stones toward better ones. This matters because a useful path through the graph may well travel through nodes that don’t themselves satisfy the filter, and refusing to traverse through them at all — rather than merely refusing to return them as final results — can sever the very connectivity the search needs to reach the true best answer. In practice, this approach tends to preserve recall surprisingly well even under fairly selective filters, since most of the graph’s structural connectivity remains intact for traversal purposes even though only a subset of nodes are eligible to appear in the final results; oversampling — asking the traversal to gather noticeably more candidates than the number of final results needed — provides a further safety margin, since a wider initial pool is more likely to contain enough filter-satisfying candidates to fill out a complete top-k result even under a fairly restrictive filter.
How does vector search combine with traditional keyword search rather than replace it?
Semantic, embedding-based search and traditional keyword-based lexical search each catch different things — a keyword search reliably finds an exact term or phrase a semantic search might rank lower simply because it’s phrased unusually, while a semantic search finds conceptually related content a keyword search would miss entirely for using different words. Combining both, then merging their separately ranked result lists into a single final ranking, is a common way to get the benefits of each rather than being forced to pick one; reciprocal rank fusion, which combines two ranked lists based primarily on each result’s rank position in each list rather than the two systems’ incomparable raw scores, is one straightforward, popular way to do this merging without needing the two underlying scoring systems to be calibrated against each other. A mature database-aware query system typically decides automatically, based on filter selectivity and the specific query at hand, whether to lean on the vector index, a lexical index, or some blend of both — an example of the kind of query-planner integration discussed in this site’s page on vector database machinery.
Filtered and hybrid search round out the applications covered on this site, and the next part turns to more advanced and still-evolving territory: how HNSW handles updates and deletion in depth, how it compares against alternative graph designs, and what current research is exploring beyond the algorithm as originally published. For the underlying database machinery this page builds directly on, revisiting this site’s page on what a vector database adds on top of HNSW itself provides useful context before continuing.