Elasticsearch向量引擎

521 阅读8分钟

第 1 章 向量引擎基础

1.1 向量引擎概述

  • 定义:ES 向量引擎是支持高维向量存储与相似度搜索的功能模块,基于dense_vector字段实现语义检索。

  • 核心价值

    • 语义理解:将文本、图像等转为向量,捕捉语义关联(如 “苹果” 与 “iPhone” 的向量相似性)。
    • 混合搜索:结合关键词过滤与向量排序,提升搜索精准度。
  • 典型应用:语义搜索、推荐系统、图像检索、异常检测。

1.2 核心概念

  • 向量表示

    • 密集向量(Dense Vector) :固定维度的实数数组(如 768 维),由 BERT 等模型生成17。
    • 相似度算法:余弦相似度、欧氏距离、点积(Dot Product)。
  • 向量搜索 vs 传统搜索

    传统搜索向量搜索
    基于关键词匹配基于语义相似度
    依赖分词器与词典依赖预训练模型(如 BERT)
    无法理解语义关联能捕捉语义相近内容

1.3 逻辑图:向量搜索全流程

graph TD
输入查询 --> 文本/图像-向量 --> ES向量引擎检索 --> 返回相似文档

第 2 章 向量引擎实现原理

2.1 向量字段类型

  • dense_vector字段配置

    PUT my_index
    {
      "mappings": {
        "properties": {
          "text_vector": {
            "type": "dense_vector",
            "dims": 768,            // 向量维度
            "index": true,          // 启用向量索引
            "similarity": "cosine"  // 相似度算法
          }
        }
      }
    }
    
    • 参数说明

    • dims:维度(≤2048),需与生成向量一致。该向量字段中每个向量的维度为 768,即每个向量由 768 个连续的数值(通常是浮点数)组成。

      举几个具体场景理解:

      1. 文本嵌入向量
        当使用 BERT-base 等预训练模型生成文本嵌入时,输出的向量维度通常是 768。例如,一句 "今天天气很好" 经过模型处理后,会转化为一个包含 768 个浮点数的数组:
        [0.123, -0.456, 0.789, ..., 0.321](共 768 个数值)
      2. 图像特征向量
        某些轻量级图像特征提取模型(如简化版 ResNet)可能输出 768 维向量。一张猫的图片经过处理后,会生成 768 个数值来描述其视觉特征(颜色、轮廓、纹理等)。
      3. 用户行为向量
        在推荐系统中,用户的行为序列(如浏览、购买记录)可能被编码为 768 维向量,每个数值代表用户在某个潜在特征维度上的偏好强度。

      维度是向量的核心属性,768 这个数值是许多主流模型(如 BERT-base、Sentence-BERT 等)的默认输出维度,平衡了表达能力和计算效率。在 Elasticsearch 中,dims必须与实际写入的向量维度严格一致,否则会导致数据写入失败。

    • similarity:支持cosinedot_productl2_norm等。

      1. cosine(余弦相似度)

      • 原理:计算两个向量夹角的余弦值,取值范围为[-1, 1],值越接近 1 表示方向越相似。
        公式:cosθ = (A·B) / (||A|| × ||B||),其中A·B是向量点积,||A||||B||是向量的 L2 范数(模长)。

      • 特点

        • 只关注向量方向的相似性,不受向量模长(数值大小)影响。
        • 适合文本嵌入、语义搜索等场景(语义相似性更依赖方向而非强度)。

      2. l2_norm(欧氏距离,L2 距离)

      • 原理:计算两个向量在 n 维空间中的直线距离,值越小表示越相似。
        公式:L2(A,B) = √[(A₁-B₁)² + (A₂-B₂)² + ... + (Aₙ-Bₙ)²]

      • 特点

        • 受向量模长影响(模长大的向量会放大距离)。
        • 适合图像特征、推荐系统等对数值大小敏感的场景(如像素强度、行为频次)。

      3. dot_product(点积)

      • 原理:计算两个向量的内积,值越大表示越相似(需注意向量模长的影响)。
        公式:A·B = A₁B₁ + A₂B₂ + ... + AₙBₙ

      • 特点

        • 结果受向量模长影响(模长大的向量点积更大)。
        • 若向量已归一化(模长为 1),则点积等价于余弦相似度。
        • 适合需要保留向量强度信息的场景(如特征重要性加权)。

      算法对比与选择建议

      算法核心关注受模长影响典型应用场景
      cosine向量方向文本语义搜索、情感分析
      l2_norm空间距离图像检索、推荐系统
      dot_product向量重叠度归一化向量场景、特征匹配

2.2 索引算法:HNSW

  • 原理:分层图结构加速近似最近邻搜索(ANN),通过调整参数平衡速度与精度。

  • 关键参数

    • m:每个节点的最大连接数(默认 16),值越大索引质量越高,但内存消耗增加。
    • ef_construction:索引构建时的候选集大小(默认 256),值越大索引越精确。
    • ef_search:搜索时的候选集大小,值越大召回率越高,但速度变慢。
  • 配置示例

    PUT my_index/_settings
    {
      "index.knn": true,
      "index.knn.algo_param.m": 32,
      "index.knn.algo_param.ef_construction": 512
    }
    

2.3 查询方式

  • 近似 kNN 搜索(推荐)

    GET /my_index/_search
    {
      "knn": {
        "field": "text_vector",
        "query_vector": [0.1, 0.2, ..., 0.7],  // 目标向量
        "k": 10,                              // 返回数量
        "num_candidates": 100                 // 候选集大小
      }
    }
    
  • 精确暴力搜索

    GET /my_index/_search
    {
      "query": {
        "script_score": {
          "query": { "match_all": {} },
          "script": {
            "source": "cosineSimilarity(params.queryVector, 'text_vector') + 1.0",
            "params": { "queryVector": [0.1, ..., 0.7] }
          }
        }
      }
    }
    
  • 参数说明

  1. "field": "text_vector"

    • 指定要进行相似性搜索的向量字段名,这里是text_vector(需与映射中定义的向量字段名称一致)。
    • 该字段必须是dense_vector类型,且已配置索引("index": true)。
  2. "query_vector": [0.1, 0.2, ..., 0.7]

    • 表示用于搜索的 "目标向量",即你要以此为基准,寻找与之相似的其他向量。
    • 向量的维度必须与text_vector字段定义的dims(如 768)完全一致,否则会报错。
    • 实际使用中,这个向量通常是由模型生成的(如文本嵌入、图像特征向量)。
  3. "k": 10

    • 指定最终返回与目标向量最相似的前 k 个结果(k 为正整数)。
    • 例如k=10表示返回相似度最高的 10 条数据,类似 "Top 10" 搜索结果。
  4. "num_candidates": 100

    • 用于控制近似搜索的候选集大小,是提升搜索效率的关键参数。
    • 原理:搜索时先从索引中筛选出num_candidates个较相似的候选向量(如 100 个),再从候选集中精确计算并返回前 k 个最相似的结果。
    • 取值影响:值越大,候选集越可能包含真正的相似向量(精度更高),但计算耗时更长;值越小,速度越

第 3 章 实战:构建语义搜索系统

3.1 准备工作

  • 环境

    • ES 8.0+(支持 k-NN 搜索)。
    • Python + sentence-transformers库(生成文本向量)。
  • 数据

    • 示例数据:1000 条商品描述文本。

3.2 步骤 1:Ruby生成向量并导入 ES

  • 环境准备
gem install elasticsearch
gem install numpy # 用于向量计算(需配合Ruby原生扩展)
  • 创建向量索引
require 'elasticsearch/client'
client = Elasticsearch::Client.new(hosts: 'http://localhost:9200')
# 创建包含向量字段的索引
client.indices.create(
  index: 'vector_docs',
  body: {
    mappings: {
      properties: {
        text: { type: 'text' },
        vector: {
          type: 'dense_vector',
          dims: 100 # 100维向量
        }
      }
    }
  }
)
  • 插入向量数据
# 模拟文本向量化并插入
def index_document(text)
  vector = text_to_vector(text) # 假设已实现向量化函数
  client.index(
    index: 'vector_docs',
    body: {
      text: text,
      vector: vector
    }
  )
end
# 插入示例数据
index_document("机器学习基础")
index_document("深度学习框架TensorFlow")
index_document("自然语言处理技术")
  • 向量查询
# 执行向量相似度查询
def vector_search(query_text, top_n: 5)
  query_vector = text_to_vector(query_text)
  client.search(
    index: 'vector_docs',
    body: {
      query: {
        script_score: {
          query: { match_all: {} },
          script: {
            source: "cosineSimilarity(params.query_vector, 'vector') + 1.0",
            params: { query_vector: query_vector }
          }
        }
      },
      size: top_n
    }
  )
end
# 执行查询
result = vector_search("深度学习")
result['hits']['hits'].each do |hit|
  puts "得分: #{hit['_score']}, 文本: #{hit['_source']['text']}"
end

第 4 章 性能优化与最佳实践

4.1 性能调优

  • 参数优化

    • 增大num_candidates提高召回率,但会降低速度。
    • 调整 HNSW 参数mef_construction平衡索引质量与内存占用。
  • 量化技术

    • Int8 量化:减少内存占用(如 1024 维向量从 4KB→1KB),牺牲少量精度。
    • 配置示例
      PUT my_index/_settings
      {
        "index.knn.quantization": "int8"
      }
      

4.2 内存管理

  • 内存计算

    • 向量数据内存:num_vectors * dims * 4(float 类型)。
    • HNSW 索引内存:num_vectors * 4 * m(默认 m=16)。
    • 总内存需小于节点堆外内存(通过GET _nodes/stats查询)。

4.3 混合检索策略

  • 流程

    1. 关键词过滤(如价格区间、分类)缩小范围。
    2. 向量排序(语义相似度)优化结果。
  • DSL 示例

    GET /products/_search
    {
      "query": {
        "bool": {
          "filter": { "term": { "category": "laptop" } },
          "should": [
            {
              "knn": {
                "field": "text_vector",
                "query_vector": [0.1, ..., 0.7],
                "k": 10
              }
            }
          ]
        }
      }
    }
    

第 5 章 对比分析与选型建议

5.1 ES 向量引擎 vs 专用向量数据库

维度ES 向量引擎专用向量数据库(如 Milvus)
核心优势全栈搜索能力,易于集成高性能向量搜索,支持亿级数据
适用场景混合搜索(关键词 + 向量)纯向量搜索(如推荐系统)
性能中等,适合中小规模数据高,适合大规模数据
成本低(无需额外部署)高(需独立集群)

5.2 选型建议

  • 中小规模混合搜索:优先 ES 向量引擎。
  • 大规模纯向量搜索:ES+Milvus 结合,ES 过滤数据,Milvus 优化排序。