Optimize the filtering mechanism for vector retrieval

更新时间:
复制 MD 格式

By default, vector retrieval scans only 1% of your documents. When a filter condition matches very few documents, that 1% scan often misses them entirely — returning sparse results or none at all. Filter optimization solves this by using inverted indexes to locate matching documents first, then computing vector similarity only on those documents.

How it works

When filter optimization is enabled, the system runs a pre-query using inverted indexes instead of scanning a fixed percentage of vectors. The decision logic works as follows:

  1. The system rewrites filter conditions as inverted index queries (see Filter expression support) and fetches up to prefetch_size results (default: 500).

  2. Fewer than `prefetch_size` results returned — the matching document set is small. The system calculates vector similarity directly on those results.

  3. `prefetch_size` or more results returned — the system checks whether the document ID of the last result represents greater than or equal to prefetch_coverage (default: 0.8) of the total document set.

    • At or above the threshold: Few documents match the filter. The system fetches the remaining matches, then calculates vector similarity.

    • Below the threshold: Many documents match. The system falls back to standard vector retrieval.

Filter optimization flow

Example

You have 1,000,000 documents, 600 of which match count = 1. With prefetch_size = 500 and prefetch_coverage = 0.8:

  1. Pre-query: The system fetches 600 documents using count = 1 as an inverted query condition. Because 600 > 500, proportion calculation runs.

  2. Proportion check: The system checks whether the 500th result's document ID meets or exceeds 80% of all document IDs. If it does, the system fetches the remaining 100 documents and calculates vector similarity across all 600. If it does not, standard vector retrieval runs.

Enable filter optimization

Set vector_service.search.enable_filter_optimize to true in searchParams:

{
    "vector": [0.1, 0.2, 0.3],
    "topK": 10,
    "namespace": "123",
    "filter": "count = 1 AND tag=\"text\"",
    "searchParams": "{\"vector_service.search.enable_filter_optimize\":true}"
}
Note: Disable filter optimization when most documents pass the filter condition. In that case, the pre-query overhead increases query time without improving recall. The default value is false (disabled).

Parameters

ParameterDefaultDescription
vector_service.search.enable_filter_optimizefalseEnables filter optimization. Set to true to enable.
vector_service.search.filter_optimize_prefetch_size500Number of results to fetch in the pre-query phase.
vector_service.search.filter_optimize_prefetch_coverage0.8Proportion threshold. If the last prefetched result's document ID represents greater than or equal to this proportion of the total document set, the system treats the filter as highly selective and uses the inverted index results.

Filter expression support

The system builds single-field inverted indexes for all fields except text fields. When filter optimization runs, it rewrites filter conditions as inverted index queries where possible.

ExpressionRewritableResult
attrName = constValue (indexed field, constant value)YesattrName:'constValue'
AND — both sides rewritableYesQUERY: a:'x' AND b:'y' / FILTER: None
AND — one side not rewritablePartialQUERY: a:'x' / FILTER: b > 1
OR — both sides rewritableYesQUERY: a:'x' OR b:'y' / FILTER: None
OR — one side not rewritableNoRewriting fails; standard vector retrieval runs
in/contain (in(tag, 'text|image'))YesQUERY: tag:'text' OR tag:'image'
rangeNoNot supported in the current version

Examples

AND — fully rewritable

count = 1 AND tag = "text"

Rewrites to:

QUERY: count:'1' AND tag:'text'
FILTER: None

AND — partially rewritable

tag = 'text' AND count > 1

Rewrites to:

QUERY: tag:'text'
FILTER: count > 1

OR — fully rewritable

count = 1 OR tag = "text"

Rewrites to:

QUERY: count:'1' OR tag:'text'
FILTER: None

OR — partially rewritable (rewriting fails)

tag = 'text' OR count > 1

Rewriting fails. Standard vector retrieval runs.

in/contain

in(tag, 'text|image')

Rewrites to:

QUERY: tag:'text' OR tag:'image'