Elasticsearch 向量检索实战:dense_vector 字段配置与 kNN 查询

Elasticsearch 从 7.x 版本开始原生支持向量字段和 kNN(k 最近邻)检索,不需要额外插件就能做语义相似度搜索。
如果你的版本不低于 7.10,可以直接用 dense_vector 字段类型存储向量,再用 kNN 查询接口检索。
下面按实际操作顺序说明配置和验证方法。

确认版本与前置条件

先通过以下命令确认集群版本和节点状态:

curl -X GET "localhost:9200"
curl -X GET "localhost:9200/_cat/nodes?v"

返回的 version.number 字段就是当前版本。dense_vector 的 kNN 检索需要 7.10 及以上版本,如果版本较低,需要先升级。
另外,向量维度要和后续写入的数据严格一致,否则会报维度不匹配错误。

创建带向量字段的索引

假设用 3 维向量做演示,实际场景中常见的是 768 维或 1536 维。
创建索引时指定 dense_vector 字段和维度:

curl -X PUT "localhost:9200/vector_demo" -H 'Content-Type: application/json' -d '
{
  "mappings": {
    "properties": {
      "title": { "type": "text" },
      "embedding": {
        "type": "dense_vector",
        "dims": 3,
        "index": true,
        "similarity": "cosine"
      }
    }
  }
}'

关键参数说明:

  • dims:向量维度,必须和写入数据一致。
  • index: true:开启向量索引,kNN 查询才能生效。
  • similarity:相似度算法,可选 cosine、dot_product、l2_norm。做语义搜索通常用 cosine。

写入向量数据并验证

写入两条示例文档:

curl -X POST "localhost:9200/vector_demo/_doc/1?refresh=true" -H 'Content-Type: application/json' -d '
{ "title": "苹果手机", "embedding": [0.9, 0.1, 0.0] }'

curl -X POST "localhost:9200/vector_demo/_doc/2?refresh=true" -H 'Content-Type: application/json' -d '
{ "title": "香蕉", "embedding": [0.1, 0.9, 0.2] }'

写入后用 _search 查询确认数据已存在:

curl -X GET "localhost:9200/vector_demo/_search?pretty" -H 'Content-Type: application/json' -d '
{ "query": { "match_all": {} } }'

如果能看到两条文档且 embedding 字段完整,说明写入成功。

执行 kNN 相似度查询

用查询向量检索最相似的文档:

curl -X GET "localhost:9200/vector_demo/_search?pretty" -H 'Content-Type: application/json' -d '
{
  "knn": {
    "field": "embedding",
    "query_vector": [0.8, 0.2, 0.0],
    "k": 2,
    "num_candidates": 10
  }
}'

k 是返回结果数量,num_candidates 是每个分片参与计算的候选数量,一般设为 k 的几倍。
返回结果中 _score 越高表示越相似。
如果查询向量和文档向量维度不一致,会直接报错,需要检查写入和查询的维度是否统一。

常见坑与排查

  • 维度不匹配:写入或查询时报 dimension mismatch,先核对 dims 设置和实际数组长度。
  • kNN 查询无结果:确认索引映射中 index 为 true,且查询字段名拼写正确。
  • 相似度算法选择:cosine 适合文本嵌入,dot_product 要求向量已归一化,l2_norm 适合欧氏距离场景。
  • 性能影响:向量索引会占用额外内存和磁盘,大规模数据建议先在小数据集上验证 num_candidates 对延迟的影响。

验证检索效果

写一个简单的 Python 脚本验证结果是否符合预期:

import requests

query = {
    "knn": {
        "field": "embedding",
        "query_vector": [0.8, 0.2, 0.0],
        "k": 2,
        "num_candidates": 10
    }
}
resp = requests.get("http://localhost:9200/vector_demo/_search", json=query)
for hit in resp.json()["hits"]["hits"]:
    print(hit["_source"]["title"], hit["_score"])

预期输出中“苹果手机”的分数应高于“香蕉”。
如果结果不符合直觉,先检查向量是否来自同一个嵌入模型,不同模型产生的向量不能混用。

按以上步骤操作后,Elasticsearch 向量检索的基本链路就通了。
后续可以结合 script_score 做混合查询,或者调整 similarity 参数来适配不同的嵌入模型。

分享到:
上一篇
Vespa 使用教程:Docker 启动与检索验证
下一篇
Redis 向量检索怎么配置:RediSearch 模块加载与相似度查询
1
系统公告

泽御云中秋国庆双节活动上线:新购8折,拼团3.99元起

尊敬的用户:
泽御云“月满中秋·礼贺国庆”双节活动现已开启,活动时间为2026年9月23日至10月10日。 活动期间可享以下福利:
1. 常规云服务器新购使用优惠码“泽御中秋国庆同乐”,符合条件的订单享8折优惠。
2. 香港精品云服务器5人拼团低至3.99元,部分4核4G套餐3人拼团年付388元,续费同价。
3. 新用户购买年付云服务器,符合活动规则可赠送2个月使用时长。
4. 老用户续费季度赠15天,续费年度赠2个月;活动期间升级配置免收配置迁移手续费。
5. 推荐好友成功下单,符合条件的推荐人可获赠7天服务器使用时长。
6. 活动期间享宕机补偿标准翻倍、简单网站迁移协助及技术工单优先处理权益。
温馨提示:优惠码不适用于拼团套餐、活动轻量产品、年付订单及续费订单;拼团套餐为独立特价活动,不与赠时类福利叠加。赠送时长不可折现、退款或跨账户转移,具体规则以活动页面说明为准。
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意