问题

一个业务系统通常有两套”检索”:

  1. 关键词搜索:用户在搜索框输入”Java 教程”,ES 用 BM25 返回最匹配的文档。这是传统搜索。
  2. 语义检索:用户在 AI 对话里问”怎么学 Java”,RAG 用向量相似度从知识库召回相关内容。这是 AI 搜索。

传统做法是两套栈:ES 做关键词搜索,Milvus/Qdrant 做语义搜索。但 ES 从 8.x 开始原生支持 kNN(k-Nearest Neighbors)向量检索。于是就有一个诱人的想法:能不能只用 ES 一套,同时做关键词搜索和 RAG 语义搜索?

ES 的 kNN 做了什么

ES 8.0 引入了 dense_vector 字段类型 + knn 查询。8.12 后做了性能优化,支持 HNSW 索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// mapping 定义
{
"mappings": {
"properties": {
"content": { "type": "text" },
"content_vector": {
"type": "dense_vector",
"dims": 1536,
"index": true,
"similarity": "cosine"
}
}
}
}

// kNN 查询
{
"knn": {
"field": "content_vector",
"query_vector": [0.1, 0.2, ...],
"k": 10,
"num_candidates": 100
}
}

关键:同一个文档里,既有 content(全文搜索),又有 content_vector(语义搜索)。一次查询可以同时走两条路。

统一栈的优势

1. 架构简化

少一个向量数据库 = 少一个组件。运维、监控、数据同步管道的复杂度全部降低。

2. 混合检索天然支持

ES 可以做混合检索(Hybrid Search):BM25(关键词匹配)+ kNN(语义匹配),然后通过 RRF(Reciprocal Rank Fusion)融合结果。

这对 RAG 场景非常有价值。纯语义搜索有时会漏掉精确匹配的关键词,混合检索可以弥补。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"query": {
"bool": {
"should": [
{ "match": { "content": "Spring Boot 配置" } },
{
"knn": {
"field": "content_vector",
"query_vector": [...],
"k": 10
}
}
]
}
}
}

3. 数据模型一致

MySQL → ES 同步一套数据,同时服务于”用户搜索”和”AI 问答”。不用维护两套向量数据的同步。

统一栈的代价

1. 性能天花板比专用向量库低

ES 的 kNN 是为”搜索场景”设计的,不是为”纯向量检索”设计的。如果你的向量量级在千万级以上、查询模式是纯语义搜索(没有关键词过滤),专用向量库(Milvus/Qdrant)的延迟和吞吐明显更好。

2. 写入压力

每个文档除了存文本,还要存一个 1536 维的向量。如果你每个文档做一次 Embedding 写入,写入量是纯文本搜索的几十倍。而且 ES 里 kNN 索引的构建也需要额外资源。

3. Embedding 成本

每新增/更新一个文档,都需要调用 Embedding 模型生成向量。在 Spring AI 里这不算复杂:

1
2
3
Document doc = new Document("内容...", Map.of("title", "xxx"));
doc.setEmbedding(embeddingModel.embed(doc));
esVectorStore.add(List.of(doc));

但如果文档量大、更新频繁,Embedding API 调用会成为新的成本和性能瓶颈。

Spring AI 怎么接

Spring AI 有 ElasticsearchVectorStore

1
2
3
4
@Bean
public VectorStore vectorStore(ElasticsearchClient esClient, EmbeddingModel embeddingModel) {
return new ElasticsearchVectorStore(esClient, embeddingModel, true);
}

然后就和用其他 VectorStore 一样的 API。Spring AI 把 ES 当成一个”向量存储”,但实际上 ES 的能力远超向量存储——它可以同时做全文搜索、聚合、过滤。

这种”一个组件、多种用法”是统一栈的核心价值。

什么场景适合统一栈?

场景 是否适合 ES 统一栈
内部知识库 RAG(十万级文档) ✅ 非常适合
已有 ES 做搜索,加 RAG 能力 ✅ 零额外组件
需要混合检索(关键词 + 语义) ✅ ES 的混合检索最成熟
千万级以上纯向量检索 ❌ 专用向量库更好
毫秒级 P99 延迟要求 ⚠️ 需要压测验证

意味着什么

  1. 对大多数业务系统来说,ES 统一栈已经足够。 你的搜索量级大概率到不了需要专用向量库的程度。
  2. 混合检索(Hybrid Search)是 RAG 召回的未来方向。 纯语义不够准,纯关键词不灵活。ES 在这个方向上有天然优势。
  3. 架构选型要从”我能用什么”变成”我需要什么”。 不要因为看到别人用 Milvus 就跟着用。如果你的搜索已经在 ES 上,先试试 ES 的 kNN 够不够。

一句话:ES 统一关键词搜索 + 语义搜索的栈,在中小规模场景下成立。省一个中间件的价值,远大于”万一将来要换专用向量库”的顾虑。