0%

向量化搜索

Elasticsearch 8.X 向量搜索核心字段解析:从原理到实战落地

随着人工智能与自然语言处理技术的成熟,向量搜索(Vector Search) 已成为突破传统关键词搜索局限、实现 “语义理解式检索” 的核心技术。Elasticsearch 作为主流的分布式搜索与分析引擎,在 8.X 版本中通过 semantic_textdense_vectorsparse_vector 三种专用字段类型,构建了完整的向量存储与查询能力。本文将从嵌入向量的基础概念出发,系统拆解三种字段的特性、适用场景、实操示例及选型逻辑,帮助开发者根据业务需求快速落地智能搜索。

基础认知:嵌入向量与 Elasticsearch 向量支持

在深入字段类型前,需先明确 “嵌入向量” 的核心价值 —— 它是连接非结构化数据(文本、图像等)与机器可计算语义的桥梁。

什么是嵌入向量(Embedding)?

嵌入向量是通过深度学习模型(如 OpenAI 的 text-embedding-ada-002、Hugging Face 的 all-MiniLM-L6-v2)将非结构化数据转化的 低维数值向量。其核心特性是:

  • 语义关联性:语义相似的数据,对应的向量在高维空间中距离更近(可通过余弦相似度、点积等计算);
  • 跨模态兼容:文本、图像、音频等不同类型数据,可通过对应模型转化为同维度向量,实现 “跨模态检索”(如用文本搜图像)。

例如,“轻便夏季背包” 和 “夏日便携双肩包” 的向量余弦相似度接近 1,而与 “冬季羽绒服” 的相似度接近 0—— 这让 Elasticsearch 能突破 “关键词匹配” 的局限,理解用户的 “语义意图”。

Elasticsearch 中的向量分类

Elasticsearch 支持的嵌入向量主要分为两类,对应不同的检索需求:

向量类型 核心特征 生成来源 适用场景
密集向量(Dense Vector) 几乎所有维度非零,维度固定(如 384/1536 维) 通用语义模型(如 OpenAI、Hugging Face) 捕捉整体语义,如 RAG、推荐系统
稀疏向量(Sparse Vector) 绝大多数维度为零,仅关键词(Token)维度有值 词项级模型(如 ELSER、SPLADE) 词级精准匹配,如属性检索

三种字段类型正是为适配这两类向量及简化开发而生,下文逐一解析其核心能力。

三种向量字段类型深度拆解

dense_vector:灵活可控的密集向量存储

核心定义

dense_vector 是 Elasticsearch 中用于存储 外部生成的密集向量 的字段类型,支持自定义相似度计算逻辑,是实现复杂语义搜索的 “主力选手”。

关键特性
  • 维度固定:定义时需通过 dims 参数指定向量维度(需与生成模型的输出维度一致,如 all-MiniLM-L6-v2 为 384 维);
  • 多相似度支持:默认支持 cosine(余弦相似度,最常用)、dot_product(点积)、l2norm(欧氏距离),可按需配置;
  • 手动向量管理:向量需在外部通过模型生成(如调用 OpenAI API),再随文档写入 Elasticsearch;
  • kNN 检索优化:支持近似 k 近邻(Approximate k-NN)查询,通过 num_candidates 平衡检索精度与性能。
适用场景
  1. 已有外部嵌入管道:业务中已使用 OpenAI、Cohere 或自定义模型生成向量(如 RAG 系统中通过 langchain 生成文档向量);
  2. 复杂语义检索:需捕捉文本整体语义(如 “推荐相似商品”“检索相似文档”),即使文本无重叠关键词;
  3. 自定义排名逻辑:需结合业务规则调整相似度权重(如为 “时效性” 维度额外加分),或混合关键词查询与向量检索。
实操示例:电商商品语义搜索
步骤 1:创建索引(定义 dense_vector 字段)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 删除已有索引(可选)
DELETE /ecommerce_products

# 创建索引,指定 dense_vector 字段
PUT /ecommerce_products
{
"mappings": {
"properties": {
"product_name": { "type": "text" }, # 传统文本字段(用于关键词过滤)
"price": { "type": "double" }, # 数值字段(用于价格筛选)
"product_vector": { # 密集向量字段
"type": "dense_vector",
"dims": 384, # 与 all-MiniLM-L6-v2 模型维度一致
"index": true, # 开启索引,支持 kNN 查询
"similarity": "cosine" # 相似度计算方式:余弦相似度
}
}
}
}
步骤 2:写入文档(带外部生成的向量)

假设已通过 all-MiniLM-L6-v2 模型生成 product_vector 向量,写入商品数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST /ecommerce_products/_bulk
{ "index": { "_id": "1" } }
{
"product_name": "轻便夏季背包",
"price": 199.0,
"product_vector": [0.12, 0.34, -0.05, ..., 0.21] # 384维向量(省略中间值)
}
{ "index": { "_id": "2" } }
{
"product_name": "耐用旅行背包",
"price": 299.0,
"product_vector": [-0.23, 0.11, 0.45, ..., -0.08]
}
{ "index": { "_id": "3" } }
{
"product_name": "紧凑型日常背包",
"price": 159.0,
"product_vector": [0.09, -0.15, 0.22, ..., 0.33]
}
步骤 3:kNN 向量搜索(语义匹配)

用户查询 “夏日便携双肩包”,先通过相同模型生成查询向量 [0.10, 0.30, -0.07, ..., 0.19],再执行 kNN 搜索:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /ecommerce_products/_search
{
"knn": {
"field": "product_vector", # 向量字段
"query_vector": [0.10, 0.30, -0.07, ..., 0.19], # 查询向量
"k": 3, # 返回 Top 3 相似商品
"num_candidates": 10 # 候选集大小(建议为 k 的 5-10 倍,平衡性能)
},
"query": { # 额外添加关键词/数值过滤(混合检索)
"range": {
"price": { "lte": 200 } # 仅保留价格 ≤ 200 的商品
}
},
"_source": ["product_name", "price"] # 仅返回需要的字段
}
优缺点总结
优点 局限
灵活性高,支持任意外部模型(OpenAI、自定义模型等) 需手动管理向量生成与存储,工程成本较高(如搭建模型调用管道)
支持多相似度计算,适配不同业务场景(如推荐用点积,检索用余弦) 向量维度固定,修改需重建索引
可与关键词、数值等过滤条件混合,平衡语义相关性与业务规则 大规模数据下,kNN 查询性能依赖硬件(如 Elasticsearch 向量加速插件)

sparse_vector:词级精准的稀疏向量存储

核心定义

sparse_vector 用于存储 稀疏向量—— 这类向量的维度对应 “词项(Token)”,仅与文本核心语义相关的少数词项有非零权重(如 “轻便” 权重 0.5、“背包” 权重 0.4),绝大多数维度为零,适合需 “词级精准匹配” 的场景。

关键特性
  • 动态维度:无需预先定义维度(维度数量等于索引中所有词项的总数),仅存储 “词项 - 权重” 键值对,存储效率高;
  • 词级透明性:可直观查看哪些词项对搜索结果贡献最大(如 “防水” 权重 0.6),便于调试与优化;
  • 模型适配性:天然支持 Elasticsearch 内置的稀疏模型(如 ELSER:Elastic Learned Sparse Encoder),可通过推理端点自动生成向量;
  • 混合检索友好:常与 dense_vector 结合,用稀疏向量保证 “词级精准度”,用密集向量保证 “语义相关性”。
适用场景
  1. 词级精准匹配:需强调特定关键词的匹配(如电商搜索中 “防水”“15L” 等属性词,文档检索中 “Elasticsearch”“向量搜索” 等专业术语);
  2. 低存储成本场景:数据量庞大(如千万级文档库),需控制存储开销(稀疏向量仅存储非零值,比密集向量节省 50%+ 存储);
  3. 依赖 Elasticsearch 内置模型:使用 ELSER 等官方稀疏模型,无需外部模型调用,降低开发成本;
  4. 混合搜索增强:弥补 dense_vector 词级匹配不足的问题(如密集向量可能忽略 “防水” 等关键属性词,稀疏向量可精准捕捉)。
实操示例:文档属性检索
步骤 1:创建索引(定义 sparse_vector 字段)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 删除已有索引(可选)
DELETE /document_library

# 创建索引,指定 sparse_vector 字段
PUT /document_library
{
"mappings": {
"properties": {
"doc_title": { "type": "text" }, # 文档标题(传统文本字段)
"doc_content": { "type": "text" }, # 文档内容(传统文本字段)
"doc_sparse_vector": { # 稀疏向量字段
"type": "sparse_vector"
}
}
}
}
步骤 2:写入文档(自动生成稀疏向量)

通过 ELSER 模型推理端点自动生成 doc_sparse_vector(需提前在 Elasticsearch 中部署 ELSER 模型):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 批量写入文档,通过 ELSER 自动生成稀疏向量
POST /_bulk
{ "index": { "_index": "document_library", "_id": "1" } }
{
"doc_title": "Elasticsearch 向量搜索实战",
"doc_content": "本文介绍 Elasticsearch 8.X 中 dense_vector 与 sparse_vector 的使用方法,重点讲解 ELSER 模型的应用",
"doc_sparse_vector": { "Elasticsearch": 0.8, "向量搜索": 0.7, "dense_vector": 0.6, "sparse_vector": 0.6, "ELSER": 0.9 }
}
{ "index": { "_index": "document_library", "_id": "2" } }
{
"doc_title": "ELASTICSEARCH ELSER 模型详解",
"doc_content": "ELSER 是 Elasticsearch 内置的稀疏模型,适用于词级精准检索,支持通过推理端点自动生成稀疏向量",
"doc_sparse_vector": { "Elasticsearch": 0.8, "ELSER": 0.9, "稀疏模型": 0.7, "推理端点": 0.6 }
}
步骤 3:稀疏向量搜索(自动生成查询向量)

使用 ELSER 模型推理端点,根据用户查询 “ELSER 模型 稀疏向量” 自动生成查询向量,无需手动指定词项权重:

1
2
3
4
5
6
7
8
9
10
11
POST /document_library/_search
{
"query": {
"sparse_vector": {
"field": "doc_sparse_vector",
"inference_id": "elser_model_1", # 已部署的 ELSER 模型 ID
"query": "ELSER 模型 稀疏向量" # 原始查询文本(模型自动生成稀疏向量)
}
},
"_source": ["doc_title", "doc_content"]
}
优缺点总结
优点 局限
存储效率高,仅存储非零权重词项,适合大规模数据 语义覆盖范围有限,依赖词项匹配,难以捕捉 “同义词” 语义(如 “背包” 与 “双肩包”)
词级透明性强,可直观查看词项权重,便于调试(如 “ELSER” 权重 0.9 是核心贡献词) 依赖稀疏模型(如 ELSER),自定义模型开发成本高
支持 Elasticsearch 推理端点,无需外部模型调用,降低工程复杂度 动态维度导致无法提前预估存储开销,索引词项过多时可能影响查询性能

semantic_text:零配置的语义搜索简化方案

核心定义

semantic_text 是 Elasticsearch 8.X 引入的 简化版语义搜索字段,专为 “快速落地语义搜索” 设计。它通过 Elasticsearch 推理端点 自动完成向量的生成、存储与查询,开发者无需理解向量原理,仅需传入原始文本即可实现语义检索。

关键注意semantic_text付费 License 功能(需 Elasticsearch Gold 及以上版本),开源版不支持。

关键特性
  • 全自动化流程:索引时自动将文本拆分为 “文本块(Chunk)”(解决长文本语义丢失问题),并生成向量;查询时自动生成查询向量,零手动干预;
  • 长文本适配:支持配置 max_chunk_size(每个块最大字符数)和 overlap_size(块重叠字符数),避免长文档(如 1000 字文章)的语义断裂;
  • 简化配置:无需定义向量维度、相似度计算方式,仅需指定关联的推理模型(如 all-MiniLM-L6-v2);
  • 低门槛入门:开发者无需搭建模型调用管道,无需理解向量原理,适合语义搜索新手或快速原型验证。
适用场景
  1. 快速原型验证:需在 1 小时内搭建语义搜索 Demo(如验证 “商品语义推荐” 是否符合需求),无需投入工程资源;
  2. 非技术团队使用:运营、产品等非技术角色需配置语义搜索,无需理解向量生成逻辑;
  3. 长文本处理:如文档检索、知识库问答(如 5000 字的产品手册),自动分块功能可高效捕捉长文本的局部语义;
  4. 标准化场景:业务对向量模型无特殊要求,使用 Elasticsearch 支持的标准模型(如 all-MiniLM-L6-v2)即可满足需求。
实操示例:知识库语义检索
步骤 1:部署推理模型(前提)

先在 Elasticsearch 中部署支持 semantic_text 的模型(如 all-MiniLM-L6-v2),可通过 Kibana 模型管理界面或 API 部署。

步骤 2:创建索引(定义 semantic_text 字段)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 删除已有索引(可选)
DELETE /knowledge_base

# 创建索引,指定 semantic_text 字段
PUT /knowledge_base
{
"mappings": {
"properties": {
"kb_title": { "type": "text" }, # 知识库标题
"kb_content": { # semantic_text 字段(长文本内容)
"type": "semantic_text",
"inference_id": "all-minilm-l6-v2-1", # 已部署的模型 ID
"chunking": { # 长文本分块配置
"max_chunk_size": 512, # 每个块最大 512 字符
"overlap_size": 50 # 块之间重叠 50 字符(避免语义断裂)
}
}
}
}
}
步骤 3:写入文档(仅需原始文本)

无需手动生成向量,直接传入知识库文本即可:

1
2
3
4
5
6
7
8
9
10
11
POST /knowledge_base/_bulk
{ "index": { "_id": "1" } }
{
"kb_title": "Elasticsearch 语义搜索配置指南",
"kb_content": "Elasticsearch 8.X 中的 semantic_text 字段可自动处理向量生成与存储,无需手动管理。配置时需注意:1. 部署对应的推理模型;2. 根据文本长度调整分块参数;3. 确保使用 Gold 及以上 License。对于长文档(如超过 1000 字符),建议将 max_chunk_size 设为 512,overlap_size 设为 50,避免分块导致的语义丢失。"
}
{ "index": { "_id": "2" } }
{
"kb_title": "ELSER 模型使用教程",
"kb_content": "ELSER(Elastic Learned Sparse Encoder)是 Elasticsearch 内置的稀疏模型,适用于词级精准检索。使用 ELSER 时,需先通过 Kibana 或 API 部署模型,再在索引映射中定义 sparse_vector 字段。对于语义搜索场景,可将 ELSER 与 dense_vector 结合,实现“词级精准+语义关联”的混合检索效果。"
}
步骤 4:语义搜索(自动生成查询向量)

直接使用 semantic 查询语法,传入原始查询文本,Elasticsearch 会自动通过推理模型生成查询向量,并与索引中的向量匹配:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /knowledge_base/_search
{
"query": {
"semantic": {
"field": "kb_content", # 关联的 semantic_text 字段
"query": "如何配置 semantic_text 的分块参数" # 原始查询文本
}
},
"_source": ["kb_title", "kb_content"],
"highlight": { # 高亮匹配的文本块(可选)
"fields": {
"kb_content": {}
}
}
}

返回结果会优先展示 “分块参数配置” 相关的文档(如 _id:1 的指南),且自动高亮匹配的语义片段,无需额外配置。

优缺点总结
优点 局限
零配置上手,自动完成向量生成、存储与查询,降低语义搜索门槛 付费功能(需 Elasticsearch Gold 及以上 License),开源版不支持
内置长文本分块功能,无需手动处理长文档语义断裂问题 灵活性低,仅支持 Elasticsearch 官方适配的推理模型(如 all-MiniLM-L6-v2),不支持外部模型向量
简化开发流程,无需搭建外部模型调用管道(如 OpenAI API) 无法自定义相似度计算逻辑,仅支持默认的语义匹配规则
与 Elasticsearch 生态深度集成,可直接结合过滤、高亮等传统搜索功能 分块参数配置不当可能导致语义重复或丢失,需根据文本长度反复调试

字段类型选型指南:按业务场景匹配最优方案

选择 semantic_textdense_vector 还是 sparse_vector,核心取决于 业务需求、技术栈成熟度、成本预算 三个维度。以下是具体选型逻辑:

选型决策树

graph TD
    A[业务需求] --> B{"是否需要快速验证原型?"}
    B -->|"是,且预算允许付费"| C[优先选 semantic_text]
    B -->|"否,需自定义向量/模型"| D{"向量类型需求?"}
    D -->|"需捕捉整体语义(如 RAG、推荐)"| E[选 dense_vector]
    D -->|"需词级精准匹配(如属性检索)"| F[选 sparse_vector]
    D -->|需平衡语义与词级精准| G[混合 dense_vector + sparse_vector]

场景化选型对照表

业务场景 推荐字段类型 核心原因
快速搭建语义搜索 Demo semantic_text 零配置、自动向量生成,1 小时内可落地原型,适合验证需求
RAG 检索增强生成 dense_vector 需捕捉文档整体语义,适配外部大模型(如 GPT-4)的向量输入,支持自定义相似度
电商商品属性检索 sparse_vector(或混合) 需精准匹配 “防水”“15L” 等属性词,稀疏向量存储效率高、词级透明性强
千万级文档库检索 sparse_vector + dense_vector 稀疏向量控制存储成本,密集向量保证语义相关性,混合检索平衡性能与精度
跨模态检索(文本搜图像) dense_vector 文本、图像可通过对应模型转化为同维度密集向量,支持跨模态语义匹配
低成本开源方案 dense_vector + sparse_vector semantic_text 付费,开源场景下需用免费的 dense_vector 和 sparse_vector

实战进阶:混合向量搜索(dense + sparse)

在复杂业务场景中,单一字段类型往往无法满足需求 —— 例如 “电商商品搜索” 既需要 “语义匹配”(用户搜 “夏日轻便包” 找到 “夏季便携背包”),又需要 “属性精准匹配”(用户隐含需求 “防水”)。此时,混合 dense_vector 与 sparse_vector 是最优方案。

实战示例:电商商品混合搜索

索引映射设计(同时定义两种向量字段)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PUT /ecommerce_products_mix
{
"mappings": {
"properties": {
"product_name": { "type": "text" },
"price": { "type": "double" },
"brand": { "type": "keyword" },
"product_dense_vector": { # 密集向量字段(语义匹配)
"type": "dense_vector",
"dims": 384,
"index": true,
"similarity": "cosine"
},
"product_sparse_vector": { # 稀疏向量字段(属性匹配)
"type": "sparse_vector"
}
}
}
}
写入文档(分别生成两种向量)
  • product_dense_vector:通过 Hugging Face all-MiniLM-L6-v2 生成;
  • product_sparse_vector:通过 Elasticsearch ELSER 模型生成。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST /ecommerce_products_mix/_bulk
{ "index": { "_id": "1" } }
{
"product_name": "防水夏季轻便背包",
"price": 199.0,
"brand": "A",
"product_dense_vector": [0.5, -0.3, 0.2, ..., 0.1], # all-MiniLM 生成
"product_sparse_vector": { "防水": 0.6, "夏季": 0.4, "轻便": 0.5, "背包": 0.7 } # ELSER 生成
}
{ "index": { "_id": "2" } }
{
"product_name": "夏季便携双肩包",
"price": 179.0,
"brand": "B",
"product_dense_vector": [0.4, -0.2, 0.3, ..., 0.1], # all-MiniLM 生成
"product_sparse_vector": { "夏季": 0.4, "便携": 0.5, "双肩包": 0.7 } # ELSER 生成
}
混合搜索查询(结合两种向量评分)

通过 bool 查询的 should 子句,同时触发两种向量检索,并通过 boost 调整权重(如属性匹配权重更高,设为 1.5):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
POST /ecommerce_products_mix/_search
{
"query": {
"bool": {
"must": [
{ "range": { "price": { "lte": 200 } } }, # 价格过滤
{ "term": { "brand": "A" } } # 品牌过滤
],
"should": [
{ # 密集向量语义匹配(权重 1.0
"knn": {
"field": "product_dense_vector",
"query_vector": [0.45, -0.25, 0.25, ..., 0.1], # 搜“夏日防水轻便包”生成的向量
"k": 5,
"num_candidates": 20
}
},
{ # 稀疏向量属性匹配(权重 1.5,提升属性优先级)
"sparse_vector": {
"field": "product_sparse_vector",
"query_vector": { "防水": 0.6, "轻便": 0.5 }
}
}
]
}
},
"_source": ["product_name", "price", "brand"]
}
结果说明
  • _id:1 的商品会因 “包含防水属性”(稀疏向量匹配)和 “语义相似”(密集向量匹配)获得更高评分,排在首位;
  • _id:2 的商品虽语义相似,但缺少 “防水” 属性,评分较低,排在后面 —— 符合用户的隐含需求。

总结

Elasticsearch 8.X 的 semantic_textdense_vectorsparse_vector 三种字段类型,覆盖了从 “快速原型” 到 “复杂生产” 的全场景向量搜索需求:

  • semantic_text:为 “快速落地” 而生,适合预算充足、追求低门槛的场景;
  • dense_vector:为 “语义灵活” 而生,适合需自定义模型、复杂语义检索的场景;
  • sparse_vector:为 “精准高效” 而生,适合词级匹配、大规模数据的场景。

实际开发中,需避免 “单一字段依赖”—— 根据业务需求组合使用(如 dense + sparse 混合检索),才能在 “语义相关性”“精准度”“性能” 之间找到最佳平衡。同时,需注意向量生成模型的选择(如开源模型降低成本、大模型提升语义精度)和硬件资源的适配(如向量加速插件提升 kNN 查询性能),确保向量搜索在生产环境中稳定高效运行

欢迎关注我的其它发布渠道