Elasticsearch8向量搜索|Python教程案例
知止自律打卡-微信小程序APP
一款微信自律打卡小程序,支持自定义打卡项目、习惯记录、项目日记、专注计时与数据统计。自律打卡、学习打卡、读书打卡、健身打卡、运动打卡、减肥打卡、戒色打卡、养生打卡、戒烟、戒酒、戒熬夜等多种场景。万能打卡模板自由创建。可自定义每日打卡目标,记录习惯连续天数,可视化追踪成长进度。
了解产品详情 →
微信搜索「知止自律打卡」
1 前言
Elasticsearch 的 向量搜索(Vector Search) 是近年来为了支持语义搜索、推荐系统、图像搜索等 AI 场景而引入的重要功能。
1.1 什么是向量搜索?🧠
传统的关键字搜索匹配的是词语或短语,而 向量搜索(Vector Search) 匹配的是“语义相似性”。
举个例子:
用户搜索:如何提高网站性能?
- 传统搜索:查找包含“提高"和”性能“的文档。
- 向量搜索:找语义上与“网站优化”、“前端加速”、“服务器响应时间”相似的文章。
1.2 从哪个版本开始支持?🕰️
| 功能 | 支持版本 | 说明 |
|---|---|---|
dense_vector 字段 |
7.3+ | 支持存储向量,但无法建立索引或排序,仅能作为过滤字段使用。 |
dense_vector 支持排序和脚本评分 |
7.5+ | 可用 script_score 实现向量相似度排序(但效率较低)。 |
dense_vector + knn 支持向量索引(ANN) |
8.0+ | 正式支持原生 KNN 近似向量搜索(使用 HNSW 算法)。这是推荐使用的方式! |
text_embedding 管道字段 |
8.11+ | 内置支持向量生成(通过 Elastic Learned Sparse Encoder 模型)。 |
1.3 与其他工具对比
| 功能 | Elasticsearch 8 | FAISS | Milvus | Weaviate |
|---|---|---|---|---|
| 原生搜索 + 向量索引 | ✅ | ❌(需外接 ES) | ❌ | ❌ |
| 支持多字段查询 | ✅ | ❌ | ❌ | ❌ |
| HNSW 向量搜索 | ✅ | ✅ | ✅ | ✅ |
| 自带嵌入模型(E5/ELSE) | ✅ | ❌ | ❌ | ✅(部分) |
1.4 许可说明
Elasticsearch 的原生向量索引(index: true)功能属于 Elastic License,不是 Apache 2.0 免费许可。
如果你用的是 OpenSearch(ES 7.10 分支开源版本),其向量功能和支持程度也不同。
2 核心特性(以 Elasticsearch 8.x 为主)
2.1 dense_vector 字段类型
"content_vector": {
"type": "dense_vector",
"dims": 384,
"index": true,
"similarity": "cosine"
}
dims:向量维度(必须与实际向量一致)。
index: true:开启 ANN 索引(必须)。
similarity:支持 cosine, dot_product, l2_norm。
2.2 KNN 向量搜索(ANN 索引)
Elasticsearch 8.x 使用 HNSW(Hierarchical Navigable Small World)算法,允许高效的近似向量搜索(KNN)
"knn": {
"field": "content_vector",
"query_vector": [...],
"k": 3,
"num_candidates": 100
}
k: 返回最相似的前 k 条记录。
num_candidates: 从索引中选取的候选数量,越大越精确但慢。
2.3 支持模型推理(从 8.11 开始)
Elasticsearch 8.11+ 引入了内置的 text_embedding 管道处理器,允许你直接将文本变成向量(使用自带模型,无需 Python 推理):
{
"text_embedding": {
"field_map": {
"content": "content_vector"
},
"model_id": ".elser_model_2"
}
}
3 dense_vector 案例
安装依赖
sentence-transformers==4.1.0
huggingface_hub[hf_xet]
elasticsearch==8.13.0
3.1 创建索引
from elasticsearch import Elasticsearch
es = Elasticsearch(
"https://***.***.***.***:9200/",
basic_auth=("elastic", "***"),
verify_certs=False
)
index_name = "my_blog_article"
# 删除旧索引(如存在)
if es.indices.exists(index=index_name):
es.indices.delete(index=index_name)
# 创建索引映射
mapping = {
"mappings": {
"properties": {
"title": {"type": "text"},
"content": {"type": "text"},
"content_vector": {
"type": "dense_vector",
"dims": 512, # 向量维度,取决于你的模型
"index": True,
"similarity": "cosine"
}
}
}
}
es.indices.create(index=index_name, body=mapping)
3.2 插入博客文章(文本 + 向量)
from sentence_transformers import SentenceTransformer
from elasticsearch import Elasticsearch
es = Elasticsearch(
"https://***.***.***.***:9200/",
basic_auth=("elastic", "***"),
verify_certs=False
)
# 输出512维向量
model = SentenceTransformer("BAAI/bge-small-zh-v1.5")
# 示例博客文章
articles = [
{"title": "Elasticsearch 简介", "content": "Elasticsearch 是一个基于 Lucene 的搜索引擎,适用于全文检索。"},
{"title": "机器学习基础", "content": "本文介绍了机器学习中的监督学习和非监督学习方法。"},
{"title": "如何使用 Python 操作 Elasticsearch", "content": "作者:有勇气的牛排, 通过 Python 的 elasticsearch 库,可以方便地查询和插入数据。"}
]
index_name = "my_blog_article"
# 插入数据
for i, article in enumerate(articles):
vector = model.encode(article["content"]).tolist()
print(article)
print(vector)
doc = {
"title": article["title"],
"content": article["content"],
"content_vector": vector
}
es.index(index=index_name, id=i + 1, document=doc)

3.3 向量查询相似博客
from sentence_transformers import SentenceTransformer
from elasticsearch import Elasticsearch
es = Elasticsearch(
"https://***.***.***.***:9200/",
basic_auth=("elastic", "***"),
verify_certs=False
)
index_name = "my_blog_article"
# 输出512维向量
model = SentenceTransformer("BAAI/bge-small-zh-v1.5")
# query_text = "如何用 Python 查询 Elasticsearch"
query_text = "有勇气的牛排"
query_vector = model.encode(query_text).tolist()
# 使用 knn 查询(Elasticsearch 8+ 支持)
query_body = {
"knn": {
"field": "content_vector",
"query_vector": query_vector,
"k": 2,
"num_candidates": 10
},
"_source": ["title", "content"]
}
response = es.search(index=index_name, body=query_body)
for hit in response["hits"]["hits"]:
print(f"得分: {hit['_score']:.4f}")
print(f"标题: {hit['_source']['title']}")
print(f"内容: {hit['_source']['content']}\n")
输出
得分: 0.8303
标题: 如何使用 Python 操作 Elasticsearch
内容: 作者有勇气的牛排, 通过 Python 的 elasticsearch 库,可以方便地查询和插入数据。
得分: 0.6260
标题: Elasticsearch 简介
内容: Elasticsearch 是一个基于 Lucene 的搜索引擎,适用于全文检索。

标签: