Vector search(向量检索)能够帮助我们在海量数据中找到语义相似的内容,但要想真正获得「有用」的结果,仅靠向量相似度还不够——我们还需要过滤(filtering)。正确理解在向量检索中如何应用过滤,可以帮助你在「性能-召回」之间取得平衡,同时也能了解 Elasticsearch / Lucene 在过滤场景下做了哪些优化。
向量检索让我们能快速在大规模数据中找到与查询语义相近的条目。然而,「相似」并不代表「满足需求」。在很多场景中,我们还希望基于特定属性进一步缩小结果范围。
想象一下在一个 电商 网站上搜商品:纯粹的向量检索可能找到一堆外观相似的商品,但你还想按价格区间、品牌、库存、评分等条件筛选。如果没有过滤,你会被淹没在海量相似商品里,难以快速定位目标。
过滤让我们对检索结果拥有精细的控制权——不仅语义相关,还完全符合业务约束,从而带来更准确、更高效、更友好的检索体验。也正因为此,Elasticsearch 与 Apache Lucene 在「跨多类型数据高效过滤」这一点上,比许多专用向量数据库更具优势。
执行精确向量检索有两种主要方式:
dense_vector
字段映射为 flat
索引类型。此时 knn
查询会走「精确」而非「近似」路径。 在精确检索中,系统会把查询向量与索引中所有向量逐一比较。如果先应用过滤,就只需要比较满足过滤条件的向量,大大节省计算量。
因此,只要过滤条件足够严格,精确检索可能比近似检索还快。经验法则:
• 过滤后命中文档 < 10k 时,用精确检索更合适。
• 如果使用 BBQ(Better Binary Quantization)索引,由于比较更快,过滤后文档 < 100k 也推荐走精确检索。
更多细节可参考这篇博客:KNN Exact vs Approximate Search。
如果你的过滤条件几乎总是很严格,可以直接把向量字段映射为 flat
类型;具体可查看 index_options 参数。
近似向量检索(如 HNSW)牺牲一定精度来换取性能,它通过最小化昂贵的「向量比较」操作来快速定位近邻。向量字段之外的其他属性(数值、关键词等)各自拥有专用索引结构:terms 字典、posting list、doc values……
这些结构与向量索引彼此独立,所以我们有两种给向量检索加过滤的策略:
下面分别介绍两者的优缺点。
后过滤在拿到「最相似的 k 个向量」之后再应用过滤条件,所以最终结果数≤k。我们可以把 k 设大一些,但仍无法保证最后一定返回 k 条。
优点:
• 对向量检索本身零侵入,运行时逻辑完全不变。
缺点:
• 最终结果数不可控;如果过滤掉太多,可能得到的结果不足 k 条。
示例(knn query
+ bool.filter
):
{
"query": {
"bool": {
"must": {
"knn": {
"field": "image-vector",
"query_vector": [54, 10, -2],
"k": 5,
"num_candidates": 50
}
},
"filter": {
"term": {
"file-type": "png"
}
}
}
}
}
knn search
也支持用 post_filter
:
{
"knn": {
"field": "image-vector",
"query_vector": [54, 10, 2],
"k": 5,
"num_candidates": 50
},
"post_filter": {
"term": {
"file-type": "png"
}
}
}
注意:如果在 knn search
中不显式使用 post_filter
,系统会把过滤条件与 KNN 结果合并,行为等同预过滤。
预过滤会先用普通倒排/列式结构把「满足过滤条件的文档 ID」存进 BitSet。随后在遍历 HNSW 图时,每找到一个候选文档,先检查它是否在 BitSet 中;若不在就丢弃。
关键点:即便候选被丢弃,其邻居节点仍需继续探索,否则会破坏 HNSW 的图遍历特性——就像开车去加油站,即便当前道路没有加油站,你也得沿路开下去,因为它可能连通着目的地。
因此,预过滤一定比「无过滤」慢。但它能确保返回的 k 条结果全部符合过滤条件。
示例(过滤写在 knn
内部):
{
"knn": {
"field": "image-vector",
"query_vector": [54, 10, -2],
"k": 5,
"num_candidates": 50,
"filter": {
"term": {
"file-type": "png"
}
}
}
}
同样可用于 knn search
:
{
"query": {
"knn": {
"field": "image-vector",
"query_vector": [-5, 9, -12],
"k": 5,
"filter": {
"term": {
"file-type": "png"
}
}
}
}
}
Document Level Security 允许基于角色定义可见文档范围。本质上,DLS 会为角色配置一条查询,该查询过滤出的文档集合被缓存为 BitSet,并包裹到底层 Lucene Reader,使「不可见」文档对用户仿佛不存在。
在向量检索里:
• 对近似检索来说,DLS 与预过滤效果一致,具有相同的性能影响与优化策略。
• 对精确检索来说,DLS 像一般过滤一样:命中文档越少,性能越好。若 DLS 限制非常严格,可考虑直接使用精确检索。
为了确保过滤场景下的向量检索性能,Elasticsearch 官方维护了一套专门的过滤基准。
例如,在 ACORN-1 引入后,当仅 2% 向量通过过滤时,查询延迟降到了原来的 55%:
过滤是搜索系统不可或缺的一环。理解它在向量检索中的实现与取舍,是打造高效、准确搜索体验的关键。
• 当过滤非常严格时,精确检索可能更快(Elasticsearch 会自动优化)。
• 近似检索 + 预过滤会变慢,但能保证返回的 k 条结果均符合过滤条件。
• 后过滤对向量检索零侵入,但无法保证最终结果数达到 k。
祝你过滤愉快!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。