惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
The Exploit Database - CXSecurity.com
S
Secure Thoughts
A
Arctic Wolf
V
Vulnerabilities – Threatpost
S
Schneier on Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Threat Research - Cisco Blogs
AWS News Blog
AWS News Blog
NISL@THU
NISL@THU
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Palo Alto Networks Blog
L
Lohrmann on Cybersecurity
Schneier on Security
Schneier on Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Scott Helme
Scott Helme
L
LINUX DO - 最新话题
L
LangChain Blog
量子位
T
Threatpost
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
腾讯CDC
W
WeLiveSecurity
Last Week in AI
Last Week in AI
美团技术团队
The GitHub Blog
The GitHub Blog
The Last Watchdog
The Last Watchdog
C
CERT Recently Published Vulnerability Notes
月光博客
月光博客
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LINUX DO - 热门话题
Microsoft Security Blog
Microsoft Security Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Troy Hunt's Blog
Webroot Blog
Webroot Blog
云风的 BLOG
云风的 BLOG
博客园 - 叶小钗
V2EX - 技术
V2EX - 技术
雷峰网
雷峰网
Security Latest
Security Latest
小众软件
小众软件
J
Java Code Geeks
博客园 - Franky
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Spread Privacy
Spread Privacy
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Recent Commits to openclaw:main
Recent Commits to openclaw:main
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
T
The Blog of Author Tim Ferriss
M
MIT News - Artificial intelligence

博客园 - work hard work smart

使用 LangChain + Hugging Face 构建文本向量化服务 SQLAlchemy 使用详解 Python 中使用 Elasticsearch 的完整指南 Qdrant 向量数据库使用指南 OpenEvals 快速入门:LLM 评估指南 DeepEval 快速入门:LLM 应用评估指南 LangSmith 批量评估完全指南 Qwen-Agent 入门指南:快速构建智能体应用 LangSmith 集成实战:从追踪到评估的完整指南 初识 go-zero:一款让你写后端更规范、更高效的 Go 微服务框架 RAG 中为什么需要 Rerank,以及如何使用 Rerank LangChain4j RAG 核心组件与组合方式 MinerU Docker 部署指南 5 分钟上手:为 Cline 配置一个免费的 MCP 天气服务 Neo4j 图数据库安装与 Spring Boot 集成实战指南 LangFuse 实战指南:用 @observe 三行代码给 LLM 应用加上全链路追踪 Function Call 深度解析:让大模型从"嘴炮"到"实干"的技术革命 Spring AI 提示词模板实战:告别硬编码,实现提示词工程化管理 LangChain4j 实战指南:用 Java 轻松构建 AI 应用 Spring AI 对话短期记忆实战:让大模型拥有"记忆力" Spring AI 提示词工程实战:让大模型更懂你的意图 Spring AI ChatClient 深度解析:优雅构建大模型应用的利器 Spring AI Alibaba DashScopeChatModel 实战 Spring 中 SSE 流式输出的多种实现方式详解 OpenSandbox 实战指南:为 AI Agent 构建安全的代码执行沙箱 在本机启动 LangGraph 开发服务器:完整指南 DeepAgents中Backend的奥秘:让AI Agent拥有文件操作能力 为什么选择 Go 开发 Web 接口?从入门到实践 智能搜索DeepAgent笔记 RAG学习笔记2--系统查询流程 RAG学习笔记1--系统文件导入流程 百炼 WebSearch 快速入门指南 Python 连接 MongoDB 完整指南:从连接配置到增删改查实战 一行命令搞定 MongoDB 开发环境:Docker Compose 部署 + 可视化管理 使用 Attu 可视化管理 Milvus 向量数据库 在 Windows Docker 中快速安装 Milvus 2.5.6 minio使用 Spark 集群搭建 hadoop集群安装 Spring AI Alibaba 入门实战 Windows 安装 OpenClaw 实战指南 MyBatis 核心流程和原理 Idea中安装Claude code插件 Spark 编程 使用Matplotlib 绘制直方图 Flink安装部署 Flume安装 查找导致cpu过高的代码方法 JVisualVM监控远程Java进程 jmap jacoco多模块生成java单元测试报告实践 arthas 使用demo LockSupport Exchanger CyclicBarrier CountDownLatch 手把手教你用python开始第一个机器学习项目
如何使用 Elasticsearch 进行全文检索和向量检索
work hard work smart · 2026-06-20 · via 博客园 - work hard work smart

Elasticsearch 具有全文检索能力和向量检索能力。全文检索适合解决“关键词匹配、分词、相关性排序”的问题,向量检索适合解决“语义相似、意思接近但表达不同”的问题。

在实际的 AI 应用,尤其是 RAG 知识库场景中,这两种检索方式通常不会孤立使用,而是会组合起来使用:

  • 全文检索:找到和用户问题中关键词高度相关的内容
  • 向量检索:找到语义上相似的内容
  • 混合检索:同时利用关键词匹配和语义匹配,提高召回质量

本文单独介绍如何使用 Elasticsearch 实现全文检索和向量检索。


一、为什么 Elasticsearch 既能做全文检索,也能做向量检索?

Elasticsearch 最早是典型的全文搜索引擎,底层基于 Lucene,擅长处理倒排索引、分词、相关性评分等搜索场景。

随着 AI 和大模型应用的发展,Elasticsearch 也支持了向量字段和向量相似度搜索,可以将文本 embedding 之后的向量存储在 ES 中,并通过相似度算法进行检索。

所以现在的 Elasticsearch 可以同时支持两类数据:

{
  "content": "Elasticsearch 是一个分布式搜索和分析引擎",
  "content_vector": [0.12, 0.31, -0.22]
}

其中:

  • content 用于全文检索
  • content_vector 用于向量检索

二、准备索引结构

假设我们要构建一个知识库,每条文档切片包含以下字段:

  • doc_id:文档 ID
  • chunk_id:切片 ID
  • title:标题
  • content:文本内容
  • content_vector:文本向量
  • metadata:额外元数据

可以创建如下索引:

PUT knowledge_chunks
{
  "mappings": {
    "properties": {
      "doc_id": {
        "type": "keyword"
      },
      "chunk_id": {
        "type": "keyword"
      },
      "title": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      },
      "content": {
        "type": "text",
        "analyzer": "ik_max_word",
        "search_analyzer": "ik_smart"
      },
      "content_vector": {
        "type": "dense_vector",
        "dims": 1024,
        "index": true,
        "similarity": "cosine"
      },
      "metadata": {
        "type": "object",
        "enabled": true
      },
      "created_at": {
        "type": "date"
      }
    }
  }
}

这里有几个关键点。

1. text 字段用于全文检索

"content": {
  "type": "text",
  "analyzer": "ik_max_word",
  "search_analyzer": "ik_smart"
}

如果是中文场景,通常会配合 IK 分词器:

  • ik_max_word:索引阶段尽可能细粒度分词,提高召回
  • ik_smart:搜索阶段更智能地分词,减少噪音

2. dense_vector 字段用于向量检索

"content_vector": {
  "type": "dense_vector",
  "dims": 1024,
  "index": true,
  "similarity": "cosine"
}

其中:

  • dims 要和 embedding 模型输出维度一致
  • index: true 表示支持近似最近邻检索
  • similarity: cosine 表示使用余弦相似度

不同 embedding 模型的维度不同,比如 384、768、1024、1536 等,建索引时一定要保持一致。


三、写入文档和向量

在写入 ES 之前,需要先对文档进行切片,然后对每个切片生成 embedding。

例如原始文档是:

Elasticsearch 是一个分布式搜索和分析引擎,支持全文检索、结构化查询、聚合分析和向量检索。

经过 embedding 模型处理后,得到一个向量:

[0.12, -0.04, 0.33]

然后写入 ES:

POST knowledge_chunks/_doc/1
{
  "doc_id": "doc_001",
  "chunk_id": "chunk_001",
  "title": "Elasticsearch 简介",
  "content": "Elasticsearch 是一个分布式搜索和分析引擎,支持全文检索、结构化查询、聚合分析和向量检索。",
  "content_vector": [0.12, -0.04, 0.33],
  "metadata": {
    "source": "es-guide.md",
    "page": 1
  },
  "created_at": "2026-06-20T10:00:00"
}

实际使用时,content_vector 会是完整维度的向量,这里只是简化示例。


四、使用 ES 进行全文检索

全文检索主要依赖 matchmulti_matchbool 等查询。

1. 单字段全文检索

如果只搜索正文内容,可以这样写:

POST knowledge_chunks/_search
{
  "query": {
    "match": {
      "content": "Elasticsearch 如何进行全文检索"
    }
  }
}

ES 会对用户输入进行分词,然后到倒排索引中查找相关文档,并根据 BM25 算法计算相关性得分。

2. 多字段全文检索

在知识库场景中,标题和正文都可能命中,所以更常见的是 multi_match

POST knowledge_chunks/_search
{
  "query": {
    "multi_match": {
      "query": "Elasticsearch 向量检索怎么做",
      "fields": [
        "title^2",
        "content"
      ]
    }
  }
}

这里的:

"title^2"

表示标题字段权重更高。如果标题命中,得分会比正文命中更高。

3. 带过滤条件的全文检索

如果只想搜索某个文档、某个知识库、某个用户的数据,可以加 filter

POST knowledge_chunks/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "multi_match": {
            "query": "全文检索和向量检索的区别",
            "fields": [
              "title^2",
              "content"
            ]
          }
        }
      ],
      "filter": [
        {
          "term": {
            "doc_id": "doc_001"
          }
        }
      ]
    }
  }
}

must 会影响相关性评分,filter 不参与评分,适合放权限、租户、文档 ID、知识库 ID 这类精确条件。


五、使用 ES 进行向量检索

向量检索的核心思路是:

  1. 用户输入一个问题
  2. 使用 embedding 模型将问题转换成向量
  3. 用问题向量到 ES 中查找最相似的文档向量

例如用户问题是:

ES 能不能做语义搜索?

经过 embedding 模型后得到:

[0.21, -0.13, 0.08]

然后使用 knn 查询:

POST knowledge_chunks/_search
{
  "knn": {
    "field": "content_vector",
    "query_vector": [0.21, -0.13, 0.08],
    "k": 5,
    "num_candidates": 100
  },
  "_source": [
    "doc_id",
    "chunk_id",
    "title",
    "content",
    "metadata"
  ]
}

参数说明:

  • field:向量字段名
  • query_vector:用户问题的向量
  • k:最终返回最相似的前 N 条
  • num_candidates:候选数量,越大召回越充分,但查询成本也越高

一般来说:

num_candidates >= k

例如:

k = 5
num_candidates = 100

表示先从近似向量索引中召回 100 个候选,再返回最相似的 5 个。


六、带过滤条件的向量检索

实际业务中,向量检索通常也需要过滤。例如只检索某个知识库、某个用户、某个文件下的内容。

可以这样写:

POST knowledge_chunks/_search
{
  "knn": {
    "field": "content_vector",
    "query_vector": [0.21, -0.13, 0.08],
    "k": 5,
    "num_candidates": 100,
    "filter": {
      "term": {
        "doc_id": "doc_001"
      }
    }
  },
  "_source": [
    "doc_id",
    "chunk_id",
    "title",
    "content",
    "metadata"
  ]
}

这样 ES 只会在符合过滤条件的文档中进行向量相似度检索。


七、全文检索和向量检索的区别

全文检索和向量检索解决的是两类不同问题。

对比项 全文检索 向量检索
核心能力 关键词匹配 语义相似
底层方式 倒排索引 向量相似度
典型算法 BM25 cosine、dot_product、l2_norm
优点 精确、可解释、适合关键词 能理解语义,适合同义表达
缺点 对同义词、改写表达不敏感 结果可解释性较弱,依赖 embedding 质量
适合场景 标题、术语、错误码、编号、关键词 问答、知识库、语义搜索、RAG

举个例子。

用户搜索:

ES 怎么做语义搜索?

如果文档里写的是:

Elasticsearch 支持基于 dense_vector 的相似度召回。

全文检索可能因为关键词不完全匹配而得分不高。

但向量检索可以理解“语义搜索”和“相似度召回”之间的语义关系,从而更容易召回这条内容。

反过来,如果用户搜索:

ERROR_CODE_10086

这种精确错误码,全文检索通常会比向量检索更可靠。


八、混合检索:同时使用全文检索和向量检索

在 RAG 场景中,单独使用全文检索或者单独使用向量检索都可能有问题。

只用全文检索:

  • 关键词不匹配时召回不到
  • 同义表达、改写表达效果不好

只用向量检索:

  • 对专有名词、编号、代码、错误码不一定稳定
  • 结果可解释性弱
  • embedding 模型质量会直接影响召回效果

所以更推荐使用混合检索。

常见做法有两种。

方案一:分别检索,再合并排序

先执行全文检索:

POST knowledge_chunks/_search
{
  "size": 10,
  "query": {
    "multi_match": {
      "query": "Elasticsearch 如何实现向量检索",
      "fields": [
        "title^2",
        "content"
      ]
    }
  }
}

再执行向量检索:

POST knowledge_chunks/_search
{
  "knn": {
    "field": "content_vector",
    "query_vector": [0.21, -0.13, 0.08],
    "k": 10,
    "num_candidates": 100
  }
}

然后在应用层合并结果:

  1. 根据 chunk_id 去重
  2. 对全文检索分数和向量检索分数做归一化
  3. 按加权分数重新排序
  4. 取 Top N 结果交给大模型

伪代码如下:

List<SearchResult> textResults = elasticsearchFullTextSearch(query);
List<SearchResult> vectorResults = elasticsearchVectorSearch(queryVector);

Map<String, SearchResult> merged = new HashMap<>();

for (SearchResult result : textResults) {
    result.setTextScore(normalize(result.getScore()));
    merged.put(result.getChunkId(), result);
}

for (SearchResult result : vectorResults) {
    SearchResult existing = merged.get(result.getChunkId());
    if (existing == null) {
        result.setVectorScore(normalize(result.getScore()));
        merged.put(result.getChunkId(), result);
    } else {
        existing.setVectorScore(normalize(result.getScore()));
    }
}

List<SearchResult> finalResults = merged.values().stream()
    .peek(result -> result.setFinalScore(
        result.getTextScore() * 0.4 + result.getVectorScore() * 0.6
    ))
    .sorted(Comparator.comparing(SearchResult::getFinalScore).reversed())
    .limit(5)
    .toList();

这种方式最灵活,也最容易控制业务逻辑。

方案二:使用 ES 的混合查询

部分 Elasticsearch 版本支持在一次查询中同时使用 queryknn

POST knowledge_chunks/_search
{
  "size": 5,
  "query": {
    "multi_match": {
      "query": "Elasticsearch 如何实现向量检索",
      "fields": [
        "title^2",
        "content"
      ]
    }
  },
  "knn": {
    "field": "content_vector",
    "query_vector": [0.21, -0.13, 0.08],
    "k": 10,
    "num_candidates": 100
  }
}

这种方式写起来更简单,但是不同 ES 版本对混合查询的支持方式可能不同,实际使用时需要结合具体版本确认。

如果业务需要更精细的去重、归一化、重排序、权限过滤,通常还是建议在应用层分别检索后合并。


九、RAG 场景中的推荐流程

在知识库问答系统中,可以采用如下流程:

用户问题
   |
   v
问题改写 / 查询增强
   |
   v
生成 query embedding
   |
   v
全文检索 + 向量检索
   |
   v
结果合并去重
   |
   v
重排序 rerank
   |
   v
拼接上下文
   |
   v
调用大模型生成答案

其中 ES 主要负责:

  • 存储文档切片
  • 存储切片向量
  • 执行全文检索
  • 执行向量检索
  • 支持过滤条件,比如知识库 ID、文件 ID、用户 ID

大模型主要负责:

  • 理解用户问题
  • 生成 query embedding
  • 根据召回内容生成自然语言答案

十、在 Java 中如何调用

如果项目是 Java 或 Spring Boot,可以通过 Elasticsearch Java Client 调用。

全文检索示例:

SearchResponse<KnowledgeChunk> response = client.search(s -> s
        .index("knowledge_chunks")
        .query(q -> q
                .multiMatch(m -> m
                        .query("Elasticsearch 如何实现全文检索")
                        .fields("title^2", "content")
                )
        )
        .size(5),
    KnowledgeChunk.class
);

向量检索示例:

SearchResponse<KnowledgeChunk> response = client.search(s -> s
        .index("knowledge_chunks")
        .knn(knn -> knn
                .field("content_vector")
                .queryVector(queryVector)
                .k(5)
                .numCandidates(100)
        )
        .source(src -> src
                .filter(f -> f
                        .includes("doc_id", "chunk_id", "title", "content", "metadata")
                )
        ),
    KnowledgeChunk.class
);

如果使用 Spring AI,也可以把 Elasticsearch 作为 VectorStore 的实现,让框架帮我们封装一部分向量写入和相似度搜索逻辑。


十一、实践建议

1. 文档切片不要太大

如果切片太大,召回结果会包含很多无关内容;如果切片太小,又可能缺少上下文。

常见切片大小可以从下面范围开始调试:

chunk size: 500 ~ 1000 tokens
overlap: 50 ~ 150 tokens

具体大小要结合业务文档类型调整。

2. 向量维度必须和索引 mapping 一致

如果 mapping 中定义:

"dims": 1024

那么写入的每个向量都必须是 1024 维,否则会写入失败。

3. 不要只依赖向量检索

向量检索擅长语义召回,但对于以下内容,全文检索通常更可靠:

  • 订单号
  • 错误码
  • 类名
  • 方法名
  • API 名称
  • 专有名词
  • 精确短语

所以生产环境更推荐混合检索。

4. 需要做权限过滤

如果是多用户、多租户知识库,检索时必须增加过滤条件,例如:

"filter": {
  "term": {
    "user_id": "user_001"
  }
}

避免用户检索到不属于自己的文档内容。

5. 检索后最好增加 rerank

全文检索和向量检索负责召回,召回结果不一定是最终最适合给大模型的内容。

可以在召回 Top 20 或 Top 50 后,再通过 rerank 模型重新排序,最后取 Top 5 或 Top 10 作为上下文。


十二、总结

Elasticsearch 现在不仅可以做传统的全文检索,也可以做向量检索,非常适合作为 RAG 知识库的检索底座。

全文检索适合解决关键词匹配问题,向量检索适合解决语义相似问题。两者各有优势,也各有短板。

在真实业务中,更推荐使用混合检索:

全文检索负责精确匹配
向量检索负责语义召回
应用层负责合并、去重、重排序
大模型负责基于上下文生成答案

这样既能保证关键词、术语、错误码等精确内容不丢失,也能提升用户自然语言提问时的语义召回效果。

对于 AI 知识库、智能问答、企业文档搜索等场景,Elasticsearch 的全文检索 + 向量检索组合,是一个非常实用且容易落地的方案。