Elasticsearch向量搜索入门 – wiki基地


Elasticsearch 向量搜索入门:从概念到实践的详细指南

引言:信息爆炸时代的搜索新范式

在当今数字化的世界里,信息以前所未有的速度增长。传统的基于关键词匹配的搜索方法,虽然在过去发挥了巨大作用,但在处理复杂、模糊或需要理解上下文的查询时,往往显得力不从心。例如,搜索“一张蔚蓝的天空下,一个小孩在草地上奔跑”这样的图片,或者找到与“区块链技术在金融领域的应用”在语义上相关的文档,仅仅依靠关键词“天空”、“小孩”、“草地”或“区块链”、“金融”是远远不够的。我们需要一种更能理解信息“含义”的搜索方式。

这就是向量搜索(Vector Search)应运而生的地方。向量搜索是一种利用机器学习模型将文本、图像、音频等各种非结构化数据转换成高维数值向量(即“嵌入”,Embeddings),然后通过计算这些向量之间的相似度来查找相关信息的技术。如果两个向量在向量空间中距离很近(或角度很小),则认为它们所代表的原始数据在语义或内容上是相似的。

作为一款强大的分布式搜索和分析引擎,Elasticsearch 不仅擅长全文搜索、结构化数据搜索和聚合分析,也在近年来紧跟人工智能和机器学习的浪潮,加入了对向量搜索的强大支持。将向量搜索能力集成到 Elasticsearch 中,为用户提供了在一个统一平台中进行关键词搜索、结构化过滤和向量相似度搜索的能力,极大地扩展了其应用场景。

本文将带您深入了解 Elasticsearch 中的向量搜索。我们将从基本概念讲起,逐步深入到如何在 Elasticsearch 中配置、索引向量数据,并执行高效的向量搜索(包括纯粹的 k-NN 搜索和强大的混合搜索)。无论您是 Elasticsearch 的新手还是资深用户,希望本文都能帮助您快速掌握这一前沿技术。

第一部分:核心概念——理解向量与相似度

在深入 Elasticsearch 的具体实现之前,我们必须先理解向量搜索的几个核心概念。

1. 向量 (Vector)

在数学和物理中,向量是具有大小和方向的量。在机器学习和信息检索领域,我们将向量视为一个有序的数值列表,用来表示数据点的特征或语义信息。例如,一个二维向量 (3, 4) 可以表示平面上的一个点或一个方向。在向量搜索中,我们处理的是高维向量,其维度可以从几十维到几千维不等,每一维的数值都是由复杂的机器学习模型(如深度神经网络)计算得出的,试图捕捉原始数据的某种属性或含义。

例如,通过一个预训练的文本 embedding 模型,句子“我喜欢吃苹果”可能被转换成一个 768 维的向量,而句子“苹果是一种健康的水果”也可能被转换成另一个 768 维的向量。如果这两个句子的含义相关,它们的向量在 768 维空间中就会比较接近。

2. 嵌入 (Embedding)

嵌入(Embedding)是机器学习模型将原始数据(如文本、图像、声音、用户行为等)映射到低维或高维向量空间的过程或结果。这个过程通常是由复杂的深度学习模型(如 Word2Vec, GloVe, BERT, CLIP, Sentence-Transformers 等)完成的。模型的训练目标是使得在向量空间中,语义或内容上相似的数据点对应的向量距离较近,而不相似的数据点对应的向量距离较远。

因此,进行向量搜索的第一步通常是生成嵌入。这通常在 Elasticsearch 之外完成,使用专门的机器学习模型和库。Elasticsearch 负责存储这些生成的向量,并提供高效的搜索能力。

3. 相似度计算 (Similarity Metrics)

向量搜索的核心是计算向量之间的“相似度”。相似度越高,意味着原始数据越相关。相似度通常通过计算两个向量之间的“距离”或“角度”来衡量。常用的相似度计算方法(或距离度量)包括:

  • 余弦相似度 (Cosine Similarity):衡量两个向量在方向上的相似性,而不考虑它们的大小(模长)。其值域通常在 [-1, 1] 之间,1 表示方向完全一致,-1 表示方向完全相反,0 表示相互正交(无关)。在许多应用中,特别是文本相似度,余弦相似度是一个非常有效的度量。Elasticsearch 使用余弦距离,即 1 - cosine_similarity
  • 点积 (Dot Product):也称内积。计算两个向量对应元素的乘积之和。点积与向量的模长和它们之间夹角的余弦值都有关。对于归一化的向量(模长为 1),点积就等同于余弦相似度。对于未归一化的向量,点积越大通常表示向量越相似。Elasticsearch 支持点积。
  • 欧几里得距离 (Euclidean Distance / L2 Distance):两个向量在向量空间中直线距离。距离越近,相似度越高。欧几里得距离计算公式为 sqrt(sum((a_i - b_i)^2))。Elasticsearch 使用 L2 距离。
  • 汉明距离 (Hamming Distance):主要用于二进制向量,计算两个等长二进制向量之间对应位置不同元素的个数。在向量搜索中较少用于表示语义相似度,更多用于查找位串差异。Elasticsearch 通常不直接支持用于高维浮点向量的汉明距离。

在 Elasticsearch 中,您可以在映射配置中指定使用哪种相似度计算方法。选择哪种方法取决于您使用的 Embedding 模型以及模型的训练方式。例如,有些文本 embedding 模型在训练时就倾向于使余弦相似度能够很好地衡量语义相似性。

4. k 最近邻搜索 (k-Nearest Neighbor / k-NN Search)

向量搜索的典型查询是找到与给定查询向量最相似的 k 个向量。这就是 k 最近邻 (k-NN) 搜索。

然而,在高维空间中,计算查询向量与所有索引向量的精确距离,然后找出最近的 k 个,这种暴力(Brute-force)搜索的计算复杂度非常高,尤其是在数据量庞大时,性能会非常差,难以满足实时搜索的需求。

因此,实际应用中通常采用近似最近邻 (Approximate Nearest Neighbor / ANN) 搜索算法。ANN 算法通过构建特殊的索引结构(如树、图或哈希表),牺牲一定的搜索精度来换取极高的搜索速度。ANN 搜索无法保证找到绝对最近的 k 个邻居,但通常能找到非常接近的 k 个邻居,而且速度远快于暴力搜索。

Elasticsearch 主要采用 分层可导航小世界图 (Hierarchical Navigable Small World / HNSW) 算法来实现 ANN 搜索。HNSW 是一种基于图结构的 ANN 算法,它构建一个多层图,通过在图上进行高效的遍历来快速定位近似的最近邻。HNSW 在搜索速度、内存占用和构建时间之间取得了很好的平衡,是目前向量数据库和支持向量搜索的系统中广泛使用的算法。

第二部分:为什么选择 Elasticsearch 进行向量搜索?

市面上有许多专门的向量数据库(如 Milvus, Weaviate, Pinecone 等),它们在向量存储和检索方面非常专业。那么,为什么还要选择 Elasticsearch 呢?将向量搜索集成到 Elasticsearch 中有几个显著的优势:

  1. 统一的搜索平台 (Unified Search):Elasticsearch 最强大的地方在于其统一处理多种数据类型和查询方式的能力。您可以在一个查询中同时使用关键词搜索、结构化过滤(如按时间范围、用户 ID 过滤)和向量相似度搜索。这使得实现“混合搜索”(Hybrid Search)变得异常简单和高效,能够结合传统搜索的精确性和向量搜索的语义理解能力,提供更全面、更相关的搜索结果。如果您已经在使用 Elasticsearch 进行日志分析、APM、安全监控或传统的全文搜索,那么将其扩展到向量搜索可以最大化利用现有基础设施和团队技能。
  2. 成熟和稳定的生态系统 (Mature Ecosystem):Elasticsearch 及其 Elastic Stack(包括 Kibana, Logstash, Beats)是一个成熟、稳定且广泛使用的平台。它提供了强大的集群管理、数据可靠性、扩展性、监控和安全功能。相比一些新兴的向量数据库,Elasticsearch 在这些方面有着深厚的积累。
  3. 简化技术栈 (Simplified Tech Stack):如果您的应用既需要全文搜索、结构化过滤,又需要向量搜索,使用 Elasticsearch 可以避免引入额外的向量数据库,从而简化您的技术栈,降低运维成本和系统复杂度。
  4. 实时数据处理 (Real-time Data):Elasticsearch 擅长处理流式和实时数据。新产生的包含向量的数据可以很快被索引并用于实时搜索。
  5. 强大的聚合和分析能力 (Analytics & Aggregation):您可以在搜索结果上执行复杂的聚合分析,这对于理解搜索结果的分布、趋势等非常有用,是许多纯向量数据库不具备的。

当然,选择哪个平台最终取决于您的具体需求。如果您的应用场景极其纯粹,只涉及海量的向量数据且对向量搜索性能有极致要求,专门的向量数据库可能是更好的选择。但对于大多数需要整合多种搜索能力的场景,Elasticsearch 提供了一个极具吸引力的选项。

第三部分:在 Elasticsearch 中配置和索引向量数据

要在 Elasticsearch 中使用向量搜索,您需要完成以下几个步骤:

  1. 确定向量维度和相似度类型:这是由您选择的 Embedding 模型决定的。例如,使用 all-MiniLM-L6-v2 模型生成的文本 embedding 通常是 384 维的,并且常用余弦相似度。使用 OpenAI 的 text-embedding-ada-002 模型生成的 embedding 是 1536 维的,常用余弦相似度或点积。
  2. 创建或修改索引映射:在索引中添加一个专门存储向量的字段,其类型必须是 dense_vector
  3. 生成向量:使用外部的 Embedding 模型工具或服务,将您的原始数据(文本、图片等)转换为数值向量。
  4. 索引文档:将原始数据连同生成的向量一起索引到 Elasticsearch 中。

1. 创建包含 dense_vector 字段的索引映射

dense_vector 是 Elasticsearch 中专门用于存储高维向量的字段类型。在创建索引时,您需要在 mappings 中定义这个字段,并指定向量的维度 (dims) 以及用于 ANN 搜索的索引选项 (index: trueindex_options: hnsw)。

以下是一个创建索引的示例请求:

json
PUT /my-vector-index
{
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 1,
"knn.algo": { // Elasticsearch 7.x/8.0-8.8 可能需要在这里配置knn算法
"enabled": true
}
}
},
"mappings": {
"properties": {
"text": { // 原始文本字段,方便理解和显示
"type": "text"
},
"image_url": { // 图片url字段,方便显示
"type": "keyword"
},
"text_vector": { // 用于存储文本向量的字段
"type": "dense_vector",
"dims": 384, // 指定向量维度,必须和您的embedding模型一致
"index": true, // 开启向量索引,用于ANN搜索
"index_options": { // HNSW索引配置
"type": "hnsw",
"m": 16, // 控制HNSW图中每个节点连接的邻居数量,影响索引大小和搜索精度
"ef_construction": 100 // 控制HNSW图构建时的搜索宽度,影响构建速度和索引精度
},
"similarity": "cosine" // 指定向量相似度计算方法 (可选,默认是l2_norm)
},
"image_vector": { // 用于存储图片向量的字段 (如果需要图片搜索)
"type": "dense_vector",
"dims": 512, // 假设图片embedding是512维
"index": true,
"index_options": {
"type": "hnsw",
"m": 24,
"ef_construction": 150
},
"similarity": "dot_product" // 假设图片embedding常用点积
}
// 可以添加其他字段,如 category, timestamp, price 等,用于过滤和混合搜索
"category": {
"type": "keyword"
},
"timestamp": {
"type": "date"
}
}
}
}

重要参数说明:

  • type: "dense_vector": 声明这是一个密集向量字段。
  • dims: 指定向量的维度。这个值必须与您使用的 embedding 模型生成的向量维度严格一致。
  • index: true: 启用这个字段的向量索引。如果不开启,您将无法进行 ANN 搜索,只能进行暴力(精确)搜索(通常不推荐)。
  • index_options: { "type": "hnsw", ... }: 配置 HNSW 索引算法。
    • type: "hnsw": 指定使用 HNSW 算法。
    • m: Maximum connections per node (最大连接数)。控制 HNSW 图中每个节点在构建过程中连接的邻居数量。较大的 m 值会创建更稠密的图,可能提高搜索精度,但会增加索引大小和构建时间。通常推荐值在 16 到 32 之间。
    • ef_construction: Construction search scope (构建搜索范围)。控制 HNSW 图构建时,算法在查找新节点的最近邻时考虑的候选邻居数量。较大的 ef_construction 值会生成更高质量的图,提高搜索精度,但会显著增加索引构建的时间和内存消耗。推荐值通常在 100 到 200 之间。
  • similarity: 相似度计算方法。指定在搜索时计算向量相似度的方法。支持 "cosine", "l2_norm", "dot_product"。如果未指定,默认使用 "l2_norm"。确保这里选择的方法与您的 embedding 模型的设计和训练方式相匹配。

注意: HNSW 参数 (m, ef_construction) 需要根据您的具体数据量、向量维度、性能要求(索引速度、搜索速度)和精度要求进行调优。通常,较大的 mef_construction 值会带来更高的搜索精度,但代价是更长的索引时间、更大的索引大小和更高的内存消耗。

2. 生成向量 (Embedding)

如前所述,向量生成通常在 Elasticsearch 外部进行。您可以使用各种工具和模型,例如:

  • 文本 Embedding: Sentence-Transformers, OpenAI API, Google AI API, Hugging Face transformers 库等。
  • 图片 Embedding: CLIP, ResNet, Vision Transformer 等模型结合适当的库(如 PyTorch, TensorFlow)。
  • 其他数据类型: 根据具体数据类型选择合适的模型。

例如,使用 Sentence-Transformers 库(Python):

“`python
from sentence_transformers import SentenceTransformer

加载模型,例如一个384维的模型

model = SentenceTransformer(‘all-MiniLM-L6-v2’)

要转换为向量的文本

text = “Elasticsearch 是一个强大的搜索和分析引擎。”

生成向量

vector = model.encode(text).tolist() # .tolist() 转换为Python列表,方便JSON序列化

print(vector)
“`

您需要编写代码来处理您的数据,调用选定的模型生成向量,并将向量与原始数据关联起来。

3. 索引文档

生成向量后,就可以将原始数据和对应的向量一起索引到 Elasticsearch 中了。使用标准的索引 API 即可:

“`json
POST /my-vector-index/_doc
{
“text”: “Elasticsearch 是一个强大的搜索和分析引擎。”,
“text_vector”: [0.1, 0.05, -0.2, …, 0.3], // 384维的向量
“category”: “技术”,
“timestamp”: “2023-10-27T10:00:00Z”
}

POST /my-vector-index/_doc
{
“text”: “向量搜索让您能够基于语义查找相似内容。”,
“text_vector”: [-0.01, 0.12, 0.3, …, -0.15], // 另一个384维的向量
“category”: “技术”,
“timestamp”: “2023-10-27T10:05:00Z”
}

POST /my-vector-index/_doc
{
“image_url”: “http://example.com/image1.jpg”,
“image_vector”: [0.5, -0.3, 0.1, …, 0.08], // 512维的图片向量
“category”: “风景”,
“timestamp”: “2023-10-27T10:10:00Z”
}
“`

确保 text_vectorimage_vector 字段的值是一个数值数组,且数组的长度严格等于映射中 dims 指定的维度。

随着文档的索引,Elasticsearch 会在后台为包含 dense_vector 字段的文档构建 HNSW 索引。这个过程需要一定的计算资源和时间,尤其是在首次索引大量数据时。

第四部分:在 Elasticsearch 中执行向量搜索

在向量数据被成功索引后,您就可以开始执行向量搜索了。Elasticsearch 主要通过 knn 查询来实现向量搜索。

1. 纯粹的 k-NN 搜索

纯粹的 k-NN 搜索只考虑向量相似度,返回与查询向量最相似的 k 个文档。

假设您想搜索与“搜索技术最新进展”相关的文档。首先,您需要使用与索引时相同的 Embedding 模型,将查询文本“搜索技术最新进展”转换为一个查询向量。然后,使用 knn 查询:

json
GET /my-vector-index/_search
{
"knn": {
"field": "text_vector", // 指定要搜索的向量字段
"query_vector": [0.2, -0.1, 0.08, ..., 0.45], // 您的查询向量 (假设也是384维)
"k": 5, // 指定返回最相似的前 k 个结果
"num_candidates": 50 // 指定在HNSW图中考虑的候选邻居数量
},
"_source": ["text", "category", "timestamp"] // 只返回这几个字段,避免返回巨大的向量
}

重要参数说明:

  • knn: 这是 Elasticsearch 用于执行向量搜索的顶级键。
  • field: 指定要执行 k-NN 搜索的 dense_vector 字段的名称。如果您有多个向量字段(如 text_vectorimage_vector),需要指定具体搜索哪个。
  • query_vector: 您的查询向量。这个向量的维度必须field 指定的字段的 dims 相匹配。
  • k: 指定要返回的最相关的文档数量(最近邻数量)。这是最终结果集的大小。
  • num_candidates: Number of candidates (候选邻居数量)。这是 ANN 算法在内部搜索过程中从 HNSW 图中检索的初始候选邻居数量。然后,Elasticsearch 会从这 num_candidates 个候选中计算精确距离,并选出最相似的 k 个。num_candidates 必须大于或等于 k。较大的 num_candidates 值通常会提高搜索精度(更有可能找到真正的最近邻),但会增加计算量,从而降低搜索速度。这是一个重要的调优参数,需要在精度和性能之间权衡。推荐值通常是 k 的几倍到几十倍,例如 k * 10k * 20

搜索结果:

Elasticsearch 将返回与查询向量最相似的 k 个文档。每个文档在搜索结果中会包含一个 _score,这个分数表示其与查询向量的相似度。具体分数的计算方式取决于您在映射中指定的 similarity 方法。对于 cosinedot_product,分数越高表示越相似;对于 l2_norm,分数越低表示越相似(因为距离越小)。

2. 混合搜索 (Hybrid Search)

混合搜索是 Elasticsearch 向量搜索能力的一大亮点,它允许您在同一个查询中结合传统的基于关键词、过滤条件的搜索与基于向量相似度的搜索。这能帮助您更精确地定位信息。

例如,您可能想找到那些在语义上与“搜索技术最新进展”相关,并且 category 字段是“技术”,并且发布时间在最近一个月内的文档。

您可以使用 bool 查询来组合不同的查询子句,将 knn 查询放在 mustfilter 中,并结合标准的 match, term, range 等查询。

json
GET /my-vector-index/_search
{
"query": {
"bool": {
"must": [
{
"match": { // 传统的全文搜索,用于匹配关键词
"text": "搜索 技术"
}
}
// 或者在must中结合knn和match
// {
// "knn": {
// "field": "text_vector",
// "query_vector": [0.2, -0.1, 0.08, ..., 0.45],
// "k": 10, // 在这里k和num_candidates需要谨慎设置,它影响的是knn子句的评分
// "num_candidates": 100
// }
// }
],
"filter": [ // 过滤条件不影响分数
{
"term": {
"category": "技术"
}
},
{
"range": {
"timestamp": {
"gte": "now-1M"
}
}
}
]
// 可以选择性地将knn放在should中,与must/filter结合进行评分
// 如果将knn放在must或filter,需要看Elasticsearch的版本和配置,有时knn本身不产生_score,
// 或者需要结合rank_eval等功能。在最新版本中,knn通常能产生分数并与其他分数合并。
}
},
"knn": { // Elasticsearch 8.1+ 版本通常将knn放在query同级
"field": "text_vector",
"query_vector": [0.2, -0.1, 0.08, ..., 0.45],
"k": 5, // 返回最终的5个结果
"num_candidates": 50 // knn内部搜索的候选数量
},
"_source": ["text", "category", "timestamp"]
}

关于 k-NN 在混合查询中的位置和评分:

在 Elasticsearch 的不同版本中,将 knn 查询与其他查询(如 match, term, range)结合的方式和评分行为有所演变。

  • 早期版本 (7.x, 8.0-8.1?)knn 通常作为一个单独的顶级查询参数出现,与 query 参数同级。在这种模式下,Elasticsearch 会首先执行 k-NN 搜索,找到最相似的 k 个文档(基于 num_candidatesk),然后对这 k 个文档应用 query 参数中的过滤和查询条件。这种方式实际上是先进行向量搜索,再进行过滤/关键词匹配。
  • 较新版本 (8.1+)knn 也可以作为 bool 查询的一个子句(通常放在 mustshould 中)。在这种模式下,knn 查询会产生一个基于向量相似度的分数,并与 bool 查询中其他子句(如 match)产生的分数合并,从而得到一个综合评分。这种方式通常能提供更灵活和强大的混合搜索能力。

示例中的混合查询说明 (基于较新版本):

上面混合查询的示例结构(queryknn 同级)是 Elasticsearch 推荐的一种混合搜索方式(尤其在 8.1 及更高版本中)。它的工作流程大致是:

  1. Elasticsearch 同时执行 query 中的布尔查询(关键词 match + 过滤 filter)和 knn 搜索。
  2. 从布尔查询的结果中(满足过滤条件的文档)和 knn 搜索的结果中(向量相似度高的文档)合并候选项。
  3. 根据不同的策略(例如 Reciprocal Rank Fusion – RRF),对这些候选项进行排序,并返回最终的 k 个结果。
  4. 布尔查询中的 filter 确保了最终结果一定符合过滤条件,而 matchknn 则共同影响最终的排序和相关性。

这种混合模式充分利用了 Elasticsearch 的现有能力,既保证了结果符合结构化/关键词要求,又考虑了语义相似性。

3. 搜索参数调优 (knum_candidates)

理解 knum_candidates 参数对于平衡搜索性能和精度至关重要:

  • k: 您最终想要返回的文档数量。这是一个业务需求决定的参数。
  • num_candidates: HNSW 搜索内部考虑的候选数量。这是一个性能和精度权衡的参数。
    • 增大 num_candidates:
      • 优点:提高搜索精度,更有可能找到真正的 k 个最近邻。
      • 缺点:增加计算量,降低搜索速度;增加内存消耗。
    • 减小 num_candidates:
      • 优点:提高搜索速度,减少计算量。
      • 缺点:降低搜索精度,可能错过一些真正的最近邻。

通常,num_candidates 设置为 k 的一个适当倍数是一个好的起点(例如 10*k100*k),然后根据您的具体需求进行性能测试和调优。您需要监控搜索延迟和召回率(Recall – 真正相关的文档被找回的比例),找到最佳的平衡点。

同时,HNSW 的构建参数 (m, ef_construction) 也影响搜索性能和精度。如果您对索引构建时间不敏感,可以适当增大 ef_construction 来提高 HNSW 图的质量,从而在搜索时可以使用较小的 num_candidates 达到同样的精度水平,或者在相同的 num_candidates 下获得更高的精度。m 的设置影响较小,但也会影响索引大小和搜索效率。

第五部分:高级考量与应用场景

掌握了基础的索引和搜索后,您可能需要考虑一些更高级的主题和实际应用场景。

1. 相似度方法选择与归一化

如前所述,similarity 参数至关重要。选择 cosine, l2_norm, 或 dot_product 取决于您的 Embedding 模型。许多文本 Embedding 模型经过训练,使得余弦相似度能很好地表示语义相似性。对于某些模型,点积也是一个有效的选择,尤其是当向量未归一化时,点积结合了方向和大小信息。如果向量已经进行 L2 归一化(即每个向量的模长为 1),那么余弦相似度和点积是等价的。了解您的 Embedding 模型如何训练以及推荐使用哪种相似度方法非常重要。

如果您需要在索引时或搜索时对向量进行归一化,Elasticsearch 提供了在映射中指定 index_options.hnsw.post_filter_normalize 或在搜索时指定 query_vector_builder 进行归一化的选项(具体取决于版本和需求),但更常见且推荐的做法是在生成 Embedding 时就进行归一化。

2. 过滤 k-NN 结果 (Filtering k-NN)

在许多场景下,您需要在执行 k-NN 搜索之前或之后应用过滤条件。例如,只搜索特定日期范围或特定类别的文档中的相似向量。

  • Post-filtering (后过滤):在 Elasticsearch 7.x 和部分 8.x 版本中,典型的混合搜索模式是先执行 k-NN 搜索(找到 k 个最相似的文档),然后在这些文档上应用其他查询或过滤条件。这种方式的缺点是如果过滤条件很严格,可能会导致最终返回的结果数量远小于 k,甚至没有结果,即使在整个索引中有符合过滤条件的相似文档。
  • Pre-filtering (预过滤 / Filtered k-NN):在 Elasticsearch 8.x 版本中得到了显著改进,支持更高效的“预过滤”或称作“Filtered k-NN”。您可以在 knn 查询中直接指定 filter 条件。Elasticsearch 会尝试利用这些过滤条件来优化 HNSW 搜索过程,只在符合过滤条件的文档子集中进行 k-NN 搜索。这大大提高了在过滤条件严格的场景下向量搜索的准确性和效率。

json
GET /my-vector-index/_search
{
"knn": {
"field": "text_vector",
"query_vector": [0.2, -0.1, 0.08, ..., 0.45],
"k": 5,
"num_candidates": 50,
"filter": { // 在knn查询中直接指定过滤条件
"bool": {
"must": [
{ "term": { "category": "技术" } },
{ "range": { "timestamp": { "gte": "now-1M" } } }
]
}
}
},
"_source": ["text", "category", "timestamp"]
}

这种带有 filter 参数的 knn 查询通常与传统的 query 结合使用,形成强大的混合搜索。

3. 性能调优

向量搜索的性能(索引速度和搜索延迟)受多种因素影响:
* 向量维度: 维度越高,计算和存储成本越大。
* 数据量: 数据量越大,索引和搜索的复杂度越高。
* HNSW 参数 (m, ef_construction, num_candidates): 这是主要的调优杠杆。
* 硬件资源: CPU 性能、内存大小(HNSW 索引常驻内存)、磁盘速度都会影响性能。
* 集群配置: 分片数量、副本数量、节点规格等。

调优通常是一个迭代过程:从一个合理的参数设置开始,进行基准测试,分析性能瓶颈,调整参数,再次测试。监控 Elasticsearch 集群的资源使用(CPU、内存、I/O)以及索引构建时间和搜索延迟是必不可少的。

4. 数据更新与删除

当文档被更新或删除时,Elasticsearch 会相应地更新或标记删除 HNSW 索引。HNSW 索引的更新不像传统倒排索引那样廉价,频繁的大量更新和删除可能会导致索引碎片化或性能下降。在某些情况下,您可能需要考虑 주기性地优化或重建索引分片来提高性能(尽管 Elasticsearch 提供了自动的合并策略)。

5. 安全与访问控制

Elasticsearch 提供了强大的安全功能(用户认证、授权、字段级安全等)。这些功能同样适用于包含向量字段的索引。您可以控制哪些用户可以访问、索引或搜索包含敏感向量数据的文档。

6. 应用场景

向量搜索在 Elasticsearch 中开启了许多新的应用场景:

  • 语义搜索: 查找与查询语句在含义上相关的文档,即使不包含完全相同的关键词。例如,输入“大耳朵的狗”,找到包含“拉布拉多犬”、“法国斗牛犬”等图片的文档。
  • 图片/视频搜索: 将图片或视频帧编码为向量,搜索视觉上相似的图片或视频片段。
  • 推荐系统: 查找与用户已喜欢或浏览过的物品(产品、文章、音乐等)向量相似的其他物品,实现“猜你喜欢”功能。
  • 问答系统: 将问题和候选答案都编码为向量,找到与问题向量最相似的答案向量。
  • 异常检测: 识别在向量空间中与其他数据点距离较远的“异常”数据点。
  • 重复数据删除: 查找非常相似的文档、图片或记录,识别潜在的重复项。
  • 产品搜索: 结合产品属性和描述的向量,查找与用户意图更匹配的产品。

第六部分:潜在问题与故障排除

在使用 Elasticsearch 向量搜索时,您可能会遇到一些问题:

  • 维度不匹配 (Dimension Mismatch):索引文档中的向量维度与映射中定义的 dims 不一致会导致索引失败。
  • 字段类型错误 (Incorrect Field Type):尝试将向量索引到非 dense_vector 字段会失败。
  • 索引构建缓慢 (Slow Indexing):HNSW 索引构建是一个计算密集型过程。如果您有大量文档或选择了较大的 mef_construction,索引时间会较长。检查集群的 CPU 和内存使用率。
  • 搜索延迟高 (High Search Latency):搜索延迟高可能是由 num_candidates 过大、硬件资源不足、网络问题或 HNSW 参数未优化导致。监控搜索请求的执行时间,并根据需要调整 num_candidates 和集群资源。
  • 搜索精度不理想 (Poor Search Accuracy):精度问题可能源于 Embedding 模型质量不高、相似度方法选择不当、HNSW 参数 (m, ef_construction, num_candidates) 设置不佳,或者在混合搜索中过滤条件与向量搜索结果冲突。
  • 内存不足 (Out of Memory):HNSW 索引占用内存。如果 mef_construction 设置过大,或者数据量巨大,可能会导致内存不足。监控节点的内存使用率。

遇到问题时,首先检查 Elasticsearch 的日志,它们通常会提供详细的错误信息。然后,逐步检查映射配置、索引数据、查询语法和性能参数。Elasticsearch 提供了丰富的监控工具(通过 Kibana 或 API)来帮助您诊断问题。

结论

Elasticsearch 对向量搜索的支持为其强大的搜索和分析能力家族增添了重要一员。通过将高维向量索引到 dense_vector 字段并利用 HNSW 算法进行高效的 ANN 搜索,Elasticsearch 使得在海量数据中进行语义相似度搜索成为可能。

更重要的是,Elasticsearch 允许您无缝地将向量搜索与传统的关键词搜索、结构化过滤和聚合分析结合起来,实现功能强大的混合搜索。这为构建智能、多模态的搜索应用提供了坚实的基础,无需引入复杂的独立向量数据库。

入门 Elasticsearch 向量搜索需要理解核心概念(向量、嵌入、相似度、HNSW)以及如何在 Elasticsearch 中进行相应的配置和操作(创建映射、索引文档、执行 knn 查询)。虽然生成高质量的向量本身是一个独立的课题,但一旦您拥有了这些向量,Elasticsearch 就为您提供了一个强大且灵活的平台来存储和检索它们。

从简单的纯 k-NN 搜索到复杂的混合搜索,再到性能调优和高级过滤,Elasticsearch 提供了构建下一代搜索应用所需的一切。开始探索 Elasticsearch 的向量搜索能力吧,它将开启信息检索和数据分析的新视野!

希望这篇详细的入门指南能帮助您踏上 Elasticsearch 向量搜索的学习和实践之路。祝您使用愉快!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部