1、企业级实战问题
向量组合条件查询,报 [vector] malformed query, expected [END_OBJECT] but found [FIELD_NAME] 错误,
向量查询是不支持复合条件查询吗?
GET /my_index/_search { "size":2, "_source": true, "query": { "vector": { "my_vector": { "vector": [1, 1], "topk":2 } }, "bool": { "must": [ { "match": { "my_label":"red" } } ] } } }
——问题来自:死磕 Elasticsearch 知识星球
类似问题在社群里被问到 2 次以上了!
向量搜索热度不减,所以我们非常有必要将向量搜索和普通搜索结合方式给大家讲清楚。
换句话说,向量搜索和普通搜索的组合检索才是 Elasticsearch 作为向量数据库有别于其他新兴向量数据库的发力点所在。
更多向量检索的先验知识,推荐大家阅读:
2、一边实战,一边验证
如下所有验证都是在 Elasticsearch 8.11.0 集群环境下完成的。
2.1 步骤 1: 创建索引
首先,通过PUT image-index 请求,创建了一个名为 image-index 的索引,并定义了其映射。
这个映射指定了索引中文档将包含的字段及其类型:
- image-vector:一个类型为dense_vector的字段,用于存储 ** 3 维 ** 向量数据。
- title:一个text类型的字段,用于存储图像的标题。
- file-type:一个keyword类型的字段,用于存储文件类型,如"jpeg"、"png"、"gif"等。
- my_label:另一个text类型的字段,可以用于存储任何标签信息,如颜色标签"red"、"blue"等。
PUT image-index { "mappings": { "properties": { "image-vector": { "type": "dense_vector", "dims": 3 }, "title": { "type": "text" }, "file-type": { "type": "keyword" }, "my_label": { "type": "text" } } } }
2.2 步骤 2: 批量插入数据
使用 POST /image-index/_bulk 请求,批量插入了多个文档到 image-index 索引。
每个文档包含了一个向量、标题、文件类型和标签。
这些文档反映了不同的图像信息,每个图像都有自己的向量表示、标题、文件类型和颜色标签。
POST image-index/_bulk { "index": {} } { "image-vector": [-5, 9, -12], "title": "Image A", "file-type": "jpeg", "my_label": "red" } { "index": {} } { "image-vector": [10, -2, 3], "title": "Image B", "file-type": "png", "my_label": "blue" } { "index": {} } { "image-vector": [4, 0, -1], "title": "Image C", "file-type": "gif", "my_label": "red" }
2.3 步骤3:基于已有认知尝试组合检索
knn 检索咱讲过,翻一下官方文档即可。
https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html
官方示例如下:
POST image-index/_search { "knn": { "field": "image-vector", "query_vector": [-5, 9, -12], "k": 10, "num_candidates": 100 }, "fields": [ "title", "file-type" ] }
正好和我们的示例是契合的,我们先执行一下,如下图所示,全体数据均可召回。
接下来,尝试再加上普通检索。
- 并列组合
- 大 BOOL 组合写
- 组合到内部 咱们挨个试试:
2.3.1 尝试方式一:并列组合检索
可以执行,可以召回结果数据。
但结果没有达到预期,我们过滤的 red ,召回结果里有 blue。如下图所示。
结论:并列组合检索不可行。
2.3.2 方式二:大 BOOL 组合写
按照常规逻辑的 bool 组合检索,结果发现:并不支持!
2.3.3 方式三:组合到内部
直接将过滤检索组合到 knn 内部,会报错,语法并不支持!
那,怎么办?
不能再猜了,看官方文档如何支持的?
https://www.elastic.co/guide/en/elasticsearch/reference/current/knn-search.html
官方文档给出两份答案。
2.3.4 官方答案一:Filtered kNN search
如下实现语法的核心:knn 向量检索的里面加了 filter 过滤。
POST image-index/_search { "knn": { "field": "image-vector", "query_vector": [ 54, 10, -2 ], "k": 5, "num_candidates": 50, "filter": { "match": { "my_label": "red" } } }, "fields": [ "title", "file-type", "my_label" ], "_source": false }
针对前面提到问题的解决方案,这是咱们推荐的唯一正确的检索方式。
2.3.5 官方答案二:hybrid search 混合检索
这个方式,就是咱们前面验证过的并列组合检索方式。结论和之前一致,并没有达到预期。
POST image-index/_search { "query": { "match": { "my_label": { "query": "red" } } }, "knn": { "field": "image-vector", "query_vector": [ 54, 10, -2 ], "k": 5, "num_candidates": 50, "boost": 0.1 }, "size": 10 }
3、小结
查询方式千万种,我们需要敲定适合自己业务场景的方式。
基于已有的常识组合检索是一种方式,更快的方式是结合官方文档探究。
我们既定认为的检索方式,不见得是官方推荐的方式。
官方推荐的:Filtered kNN search 查询结合了基于内容的过滤和基于向量的搜索,旨在找出既符合文本查询条件(如标签为"red")又在向量空间中与给定查询向量最接近的文档。
这样的查询在处理如图像、文档或音频等多媒体内容时特别有用,其中内容可以通过向量(例如通过机器学习模型生成的嵌入)和元数据(如标签、标题或类型)来描述。
通过这种方式,我们可以高效地找到既满足特定元数据条件又在内容上与给定示例相似的项目,这对于构建推荐系统、图像搜索引擎或其他需要结合内容和上下文信息进行精准检索的应用场景非常有价值。
此处后续版本可能有变化,更多细节,以最新版本的官方文档为准。
7 年+积累、 Elastic 创始人Shay Banon 等 15 位专家推荐的 Elasticsearch 8.X新书已上线
更短时间更快习得更多干货!
和全球 近2000+ Elastic 爱好者一起精进!
elastic6.cn——ElasticStack进阶助手
比同事抢先一步学习进阶干货!