文档首页/ 云搜索服务 CSS/ 快速入门/ 使用Elasticsearch实现向量检索
更新时间:2025-07-01 GMT+08:00

使用Elasticsearch实现向量检索

随着深度学习技术的不断发展,基于语义向量的检索方法通过将文本、图像等非结构化数据映射到高维向量空间,使相似内容在向量空间中距离相近。相比传统的关键词匹配检索,这种语义层面的相似性计算能显著提升召回率和准确率。该技术已成功应用于图像搜索、视频内容检索、人脸识别、个性化广告推荐等诸多场景,大幅提升了相关应用的实际效果。

本章节为您提供了一个通过Elasticsearch集群实现向量检索的示例,您可以参考此示例了解CSS向量数据库,包括创建向量索引、导入向量数据、向量检索等操作。

场景描述

某电商平台希望提升商品搜索的准确率,通过深度学习模型将商品图片转换为语义向量,并结合价格、名称等属性存储至Elasticsearch集群。用户可通过以下方式实现混合搜索:

  • 纯向量检索:查找与目标图片最相似的商品。
  • 过滤检索:在指定价格区间内查找相似商品。
  • 组合查询:结合关键词与向量相似度进行搜索。

假设该电商网站经营商品的向量数据如下所示:

{
  "products":[
    {"productName":"2017秋装新款文艺衬衫女装","image_vector":[1.0, 1.0],"price":100.0}
    {"productName":"2017秋装新款文艺衬衫女装","image_vector":[1.0, 2.0],"price":200.0}
    {"productName":"2017秋装新款文艺衬衫女装","image_vector":[1.0, 3.0],"price":300.0}
    {"productName":"2018春装新款牛仔裤女装","image_vector":[10.0, 20.0],"price":100.0}
    {"productName":"2018春装新款牛仔裤女装","image_vector":[10.0, 30.0],"price":200.0}
    {"productName":"2017春装新款休闲裤女装","image_vector":[100.0, 200.0],"price":100.0}
    {"productName":"2017春装新款休闲裤女装","image_vector":[100.0, 300.0],"price":200.0}
  ]
}

操作流程

以下是使用Elasticsearch集群完成数据搜索的操作步骤。

开始迁移数据前,请务必按准备工作指导完成必要操作。

  1. 步骤一:创建Elasticsearch集群:创建一个非安全模式的Elasticsearch集群用于向量检索。
  2. 步骤二:登录Kibana:登录Kibana,访问集群。
  3. 步骤三:创建向量索引:创建向量索引,用于存储向量数据。
  4. 步骤四:导入向量数据:使用开源Elasticsearch API导入数据。
  5. 步骤五:向量检索:在Elasticsearch集群中对数据进行纯向量搜索和组合查询。
  6. 步骤六:删除索引:当不再使用对应的索引数据时,可以删除对应索引节约资源。

准备工作

已注册华为账号并开通华为云,进行了实名认证,且在使用云搜索服务前检查账号状态,账号不能处于欠费或冻结状态。

如果您还没有华为账号,请参考以下步骤创建。
  1. 打开华为云网站
  2. 在页面右上角单击“注册”,根据提示信息完成注册。
  3. 勾选服务条款, 单击“开通”。
  4. 实名认证,请参考:

步骤一:创建Elasticsearch集群

创建一个非安全模式的Elasticsearch集群用于向量检索。

  1. 登录云搜索服务管理控制台。
  2. 在左侧菜单栏选择集群管理 > Elasticsearch
  3. 在集群列表右上角,单击创建集群,默认进入新版创建页面。
    图1 新版创建页面
  4. 集群配置,选择集群类型和版本。
    表1 集群配置

    参数

    示例

    说明

    集群类型

    Elasticsearch

    选择“Elasticsearch”

    集群版本

    7.10.2

    选择所需的集群版本,支持的版本以界面可选项为准。

    Elasticsearch集群仅7.6.2和7.10.2版本自带CSS向量搜索引擎,如果要使用CSS向量数据库功能,则必须选择这两个版本。

  5. 基础配置,选择计费模式、当前区域和可用区。
    表2 基础配置

    参数

    示例

    说明

    计费模式

    按需计费

    选择集群的计费模式,集群支持包年/包月和按需计费两种模式。

    • 包年/包月:预付费模式,按照订单的购买周期结算。
    • 按需计费:后付费模式,按照集群实际使用时长计费,计费周期为一小时,不足一小时按一小时计费。

    当前区域

    中国-香港

    选择集群的所在区域。区域指集群的物理数据中心所在的位置,不同区域的云服务产品之间内网互不相通。建议就近选择靠近您业务的区域,可减少网络时延,提高访问速度。

    可用区

    可用区1

    选择集群工作区域下关联的可用区。可用区指在同一区域下,电力、网络隔离的物理区域,可用区之间内网互通,不同可用区之间物理隔离。

    最多支持配置3个可用区。

  6. 配置数据节点。
    数据节点用于存储集群数据,当集群未启用Master节点和Client节点时,数据节点将同时承担集群管理、存储数据、提供接入集群和分析数据的职责。此时,为保证集群中数据的稳定性,建议设置节点数量大于等于3个。
    图2 配置数据节点
    表3 数据节点配置

    参数

    示例

    说明

    CPU架构

    X86计算

    选择数据节点的CPU架构。支持“X86计算”“鲲鹏计算”,具体支持的类型由实际区域环境决定。

    节点规格

    ess.spec-4u8g

    选择数据节点的规格。单击“选择节点规格”,在弹窗中选择合适的规格。

    规格列表的“vCPUs | 内存”呈现了规格的CPU核数和内存,“建议存储范围”呈现了该规格支持的存储容量。

    不同区域支持的节点规格不同,请以实际环境为准。

    节点存储类型和容量

    • 高I/O
    • 40GB

    选择数据节点的存储类型和容量。

    • “节点规格”选择的是云硬盘时,需要选择云硬盘类型,并根据业务需要配置存储容量。
      • 不同区域支持的云硬盘类型不同,请以实际环境为准。
      • 节点存储容量的取值范围由所选的“节点规格”决定,且必须是20的倍数。
      • 节点存储容量不支持就地缩容,请评估好业务量,合理选择。
    • “节点规格”选择的是本地盘时,无需配置节点存储类型,节点存储容量是固定值,由选择的本地盘规格决定。

    节点数量

    1

    设置集群中的数据节点个数。

    • 当集群配置了Master节点,则数据节点的节点数量支持1~200。
    • 当集群未配置Master节点,则数据节点的节点数量支持1~32。
    • 建议数据节点的节点数量大于或等于3,以提升集群可用性。
  7. Master节点、Client节点和冷数据节点均保持默认值,不启用即可。
    • Master节点负责管理集群中所有节点任务,如集群元数据、索引及分片分配,保障大规模集群稳定运行,适用于需高可用性与集中管控的场景。
    • Client节点负责接收并协调外部请求(如搜索和写入),优化高负载查询和集群扩展性,适用于处理复杂查询和大规模分片场景。
    • 冷数据节点用于存储查询时延要求不高且数据量大的历史数据,适用于大规模数据集存储,有利于优化存储成本和查询性能。
  8. 网络配置,设置集群的VPC、IP地址和安全组。
    图3 网络配置
    表4 网络配置

    参数

    示例

    说明

    虚拟私有云

    vpc-default

    指定集群使用的虚拟专用网络,可以对不同业务进行网络隔离

    子网

    subnet-default

    指定集群使用的子网,通过子网提供与其他网络隔离的、可以独享的网络资源,以提高网络安全。

    选择当前虚拟私有云下的子网。

    IPv4地址

    自动分配IPv4地址

    分配集群节点的IPv4地址。

    安全组

    default

    指定集群使用的安全组,安全组起着虚拟防火墙的作用,为集群提供安全的网络访问控制策略。

    所选安全组的入方向规则中,“协议端口”必须为“全部”或包含9200的端口范围,否则外部业务访问可能会异常。

  9. 安全模式配置。关闭安全模式,本集群仅做入门指导使用,无需启用安全模式。
    • 安全模式的集群会对集群进行通讯加密和安全认证。
    • 非安全模式的集群无需安全认证即可访问,并且采用HTTP明文传输数据。建议确认访问环境的安全性,勿将访问接口暴露到公网环境上。
  10. 集群管理配置,设置集群名称、企业项目等信息。
    表5 集群管理

    参数

    示例

    说明

    集群名称

    Sample-ESCluster

    自定义集群名称。

    集群名称在4位到32位之间,必须以字母开头,可以包含字母、数字、中划线或者下划线,不能包含其他的特殊字符。

    企业项目

    default

    给集群绑定一个企业项目。

    企业项目是一种云资源管理方式,企业项目管理服务提供统一的云资源按项目管理,以及项目内的资源管理、成员管理,默认项目为“default”

    如果开通了“企业项目”,请从下拉列表中选择所在的企业项目。

    标签

    不添加

    为集群添加标签,方便用户识别和管理拥有的集群资源。

    每个集群最多可以设置20个标签。

  11. 设置集群自动备份快照。关闭自动创建集群快照,本集群仅做入门指导使用,无需备份快照。
  12. 终端节点服务等均保持默认值,不启用即可。
  13. 单击“立即创建”,开始创建集群。
  14. 返回集群列表,查看新建的集群。当集群创建成功后,“集群状态”会变为可用
    图4 查看集群状态

步骤二:登录Kibana

集群创建成功后,通过Kibana访问Elasticsearch集群。

  1. 在Elasticsearch集群列表,选择已创建的“Sample-ESCluster”集群,单击操作列中的“Kibana”进入Kibana控制台。
  2. 在Kibana的左侧导航中选择“Dev Tools”,进入Console界面。
    Console左侧区域为输入框,输入框右侧的三角形为执行命令按钮,Console右侧为结果输出区域。
    图5 Console界面

步骤三:创建向量索引

在Elasticsearch集群中创建向量索引,用于存储向量数据。

在Kibana中执行如下命令,创建向量索引“my_store”
PUT /my_store 
{
  "settings": {       		// 索引级别的配置
    "index": {
      "vector": true  		// 启用向量检索功能
    }
  },
  "mappings": {       		// 定义文档字段结构和类型
    "properties": {
      "productName": {    	// 商品名称字段(文本类型)
        "type": "text",   	// 标准文本类型,支持全文搜索
        "analyzer": "ik_smart"  // 使用ik_smart中文分词器进行智能分词
      },
      "image_vector": {   	// 图像特征向量字段
        "type": "vector", 	// 声明为向量类型
        "dimension": 2,   	// 向量维度(示例使用2维,实际场景常用512/768等高维向量)
        "indexing": true, 	// 启用向量索引以支持相似度搜索
        "algorithm": "GRAPH",  	// 使用图算法构建近似最近邻(ANN)索引
        "metric": "euclidean"  	// 使用欧氏距离作为相似度度量标准
      },
      "price": {                // 商品价格字段
        "type": "float"         // 浮点数类型,支持范围查询和数值计算
      }
    }
  }
}

返回结果如下所示:

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "my_store"
}

步骤四:导入向量数据

Elasticsearch集群支持通过多种方式导入数据,本示例选择在Kibana使用开源Elasticsearch API导入数据。

在Kibana中执行如下命令,将向量数据导入到“my_store”索引中。
POST /my_store/_doc/_bulk
{"index":{}}
{"productName":"2017秋装新款文艺衬衫女装","image_vector":[1.0, 1.0],"price":100.0}
{"index":{}}
{"productName":"2017秋装新款文艺衬衫女装","image_vector":[1.0, 2.0],"price":200.0}
{"index":{}}
{"productName":"2017秋装新款文艺衬衫女装","image_vector":[1.0, 3.0],"price":300.0}
{"index":{}}
{"productName":"2018春装新款牛仔裤女装","image_vector":[10.0, 20.0],"price":100.0}
{"index":{}}
{"productName":"2018春装新款牛仔裤女装","image_vector":[10.0, 30.0],"price":200.0}
{"index":{}}
{"productName":"2017春装新款休闲裤女装","image_vector":[100.0, 200.0],"price":100.0}
{"index":{}}
{"productName":"2017春装新款休闲裤女装","image_vector":[100.0, 300.0],"price":200.0}

当返回结果信息中“errors”字段的值为“false”时,表示导入数据成功。

步骤五:向量检索

在Elasticsearch集群中对数据进行纯向量检索和组合查询。

  • 纯向量检索

    假设用户提供了一张商品图片,想要查找相似商品。首先,集群通过向量化模型获得查询图片的特征向量,然后使用向量查询语法进行相似度查询。

    在Kibana中执行如下搜索命令:

    GET /my_store/_search
    {
      "size": 3,  			// 要求返回前3个最相关的结果
      "_source": { 
        "excludes": "image_vector"  // 排除返回结果中的image_vector字段
      }, 
      "query": {
        "vector": {  		// 启用向量搜索功能
          "image_vector": {  	// 指定目标向量字段名称(需与索引映射一致)
            "vector": [1.0, 2.0],  	// 待查询的特征向量(此处为简化示例,实际维度应与模型输出一致)
            "topk": 3  	        // 返回最相似的3个候选结果
          }
        }
      }
    }

    返回结果如下所示,Elasticsearch根据查询向量与存储的向量数据之间的相似度得分进行结果的排序。

    {
      "took" : 1,  		// 查询耗时1毫秒
      "timed_out" : false,  // 未发生查询超时
      "_shards" : {  	// 分片执行情况
        "total" : 1,  	// 总分片数
        "successful" : 1,  	// 成功执行分片数
        "skipped" : 0,  	// 跳过分片数
        "failed" : 0  	// 失败分片数
      },
      "hits" : {
        "total" : {  	// 匹配文档总数
          "value" : 3,  	// 精确匹配3条(eq表示精确计数)
          "relation" : "eq"
        },
        "max_score" : 1.0,  // 最高相似度得分(取决于向量空间的距离算法)
        "hits" : [  	// 命中文档列表(按相似度得分降序排列)
          {
            "_index" : "my_store",          // 文档所属索引
            "_type" : "_doc",  		// 文档类型,固定取值
            "_id" : "JPL5r5YBWkpNKdSUkRc9",  // 文档唯一标识符
            "_score" : 1.0,  	// 当前文档与查询向量的相似度得分
            "_source" : {  			// 存储的原始文档数据(已过滤image_vector)
              "price" : 200.0,
              "productName" : "2017秋装新款文艺衬衫女装"
            }
          },
          // ...(其他相似结果结构相同,分数递减)
        ]
      }
    }
  • 混合搜索

    假设用户提供了一张商品图片,想要查找相似商品,并且限定了价格范围。可以通过混合查询的语法实现向量检索+范围过滤。

    在Kibana中执行如下搜索命令:

    GET /my_store/_search
    {
      "size": 3,                     // 要求返回前3个最相关的结果
      "_source": { 
        "excludes": "image_vector"   // 排除返回结果中的image_vector字段
      }, 
      "query": {
        "vector": {                  // 启用向量搜索功能
          "image_vector": {          // 指定目标向量字段名称(需与索引映射一致)
            "vector": [1.0, 2.0],    // 待查询的特征向量(此处为简化示例,实际维度应与模型输出一致)
            "topk": 3,               // 返回最相似的3个候选结果
            "filter": {              // 混合过滤条件(先执行过滤再计算相似度)
              "range": {             // 价格范围过滤
                "price": {
                  "lte": 300         // 仅保留价格小于或等于300元的商品
                }
              }
            }
          }
        }
      }
    }

    查询流程:在索引中筛选出所有价格小于或等于300元的商品,计算过滤后商品的image_vector字段与待查询向量的相似度,按相似度分数降序排列(score字段),取top3相似度最高的商品,移除image_vector字段返回,保留商品价格和名称等核心信息。

    返回结果如下所示:

    {
      "took" : 1,			// 查询耗时1毫秒
      "timed_out" : false,	// 查询耗时1毫秒
      "_shards" : {			// 分片执行情况
        "total" : 1,        // 总分片数
        "successful" : 1,   // 成功执行分片数
        "skipped" : 0,      // 跳过分片数
        "failed" : 0        // 失败分片数
      },
      "hits" : {
        "total" : {			// 匹配文档总数
          "value" : 3,      // 精确匹配3条(eq表示精确计数)
          "relation" : "eq"
        },
        "max_score" : 1.0,  // 最高相似度得分(取决于向量空间的距离算法)
        "hits" : [    		// 命中文档列表(按相似度降序排列)
          {
            "_index" : "my_store",  // 文档所属索引
            "_type" : "_doc",       // 文档类型
            "_id" : "JPL5r5YBWkpNKdSUkRc9", // 文档唯一ID
            "_score" : 1.0,         // 当前文档与查询向量的相似度得分(归一化后)
            "_source" : {           // 存储的原始文档数据(已过滤image_vector)
              "price" : 200.0,
              "productName" : "2017秋装新款文艺衬衫女装"
            }
          },
          // ...(其他相似结果结构相同,分数递减)
        ]
      }
    }

步骤六:删除索引

当不再使用对应的索引数据时,可以在Kibana中执行如下命令删除对应索引,避免造成资源浪费。

DELETE /my_store

返回结果如下所示。

{
  "acknowledged" : true
}

后续步骤

已完成数据搜索业务,无需继续使用集群时,可删除集群释放资源。

由于集群删除后,数据无法恢复,请谨慎操作。

  1. 登录云搜索服务管理控制台。
  2. 在左侧菜单栏选择集群管理 > Elasticsearch
  3. 在集群列表,选择“Sample-ESCluster”集群,在操作列单击“更多”>“删除”
  4. 在弹出的确认对话框中,输入“DELETE”,单击“确定”完成操作。

相关文档