news 2026/6/22 14:47:54

Elasticsearch 结合向量检索:10 分钟为你的电商项目加上“以图搜图”和“语义搜索”功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Elasticsearch 结合向量检索:10 分钟为你的电商项目加上“以图搜图”和“语义搜索”功能

🛍️ 前言:你的搜索功能该升级了

做电商项目的兄弟们,是不是还在苦恼这些问题?

  • 用户搜“红色连衣裙”,结果搜不到标题里写着“朱砂红长裙”的商品(关键词不匹配)。
  • 用户看到一张网红同款鞋的照片,想搜同款,但不知道叫什么名字(无法以图搜图)。
  • 搜索结果虽然包含关键词,但完全不是用户想要的东西(缺乏语义理解)。

传统的倒排索引(Inverted Index)已经到了瓶颈。
今天,我们不需要引入新的数据库,直接利用Elasticsearch 8.x的原生向量检索能力,配合开源 Embedding 模型,为你的系统装上“AI 的眼睛”。


🧠 核心原理:万物皆可 Vector

以前我们存商品,存的是 text:“耐克跑鞋”。
现在我们存商品,存的是 vector(向量):[0.12, -0.98, 0.55, ...]

向量检索的魔法在于:

  1. 语义搜索:将“朱砂红长裙”和“红色连衣裙”转换成向量,它们在数学空间里距离非常近,所以能搜出来。
  2. 以图搜图:使用CLIP 模型,它能把“鞋子的图片”和“鞋子的描述文字”映射到同一个向量空间。

架构流程图:

用户请求 (文本/上传图片)
Embedding 模型 (CLIP/BERT)
生成向量 ([0.1, ...])
商品入库
模型向量化
写入 ES (dense_vector)
ES KNN 检索
返回相似商品

🛠️ Step 1: 环境准备与 Mapping 定义

首先,确保你的 Elasticsearch 版本 >= 8.0(低版本虽然也能装插件,但 8.x 原生性能最好)。

我们需要在索引中定义一个dense_vector类型的字段。

PUT/products{"mappings":{"properties":{"name":{"type":"text"},"price":{"type":"double"},"image_url":{"type":"keyword"},"product_vector":{"type":"dense_vector","dims":512,// 维度需与模型输出一致,CLIP通常是512"index":true,"similarity":"cosine"// 使用余弦相似度计算距离}}}}

🐍 Step 2: Python 脚本生成向量 (Embedding)

我们使用 OpenAI 开源的CLIP 模型,它最擅长处理“图文多模态”场景。
安装依赖:pip install sentence-transformers

fromsentence_transformersimportSentenceTransformerfromelasticsearchimportElasticsearch# 1. 连接 ESes=Elasticsearch("http://localhost:9200",basic_auth=("elastic","password"))# 2. 加载 CLIP 模型 (支持多语言和图片)# clip-ViT-B-32 是一个经典的图文匹配模型model=SentenceTransformer('clip-ViT-B-32')# 3. 模拟商品数据products=[{"name":"红色丝绒晚礼服","image":"dress.jpg"},{"name":"复古真皮马丁靴","image":"boots.jpg"}]# 4. 向量化并入库forpinproducts:# 这里演示文本向量化,如果是图片需使用 Image.open()embedding=model.encode(p["name"])doc={"name":p["name"],"product_vector":embedding.tolist()# 转为 List 存入 ES}es.index(index="products",document=doc)print(f"商品{p['name']}已入库")

🔎 Step 3: 发起 KNN 搜索

现在,用户输入了“参加晚宴穿的衣服”(注意:标题里没有这些字),我们要进行语义搜索。

# 用户查询user_query="参加晚宴穿的衣服"query_vector=model.encode(user_query).tolist()# ES KNN 搜索 DSLsearch_body={"knn":{"field":"product_vector","query_vector":query_vector,"k":10,# 返回最相似的 10 个"num_candidates":100},"_source":["name","price"]}res=es.search(index="products",body=search_body)forhitinres['hits']['hits']:print(f"推荐商品:{hit['_source']['name']}(相似度:{hit['_score']})")

预期结果:
虽然用户的搜索词里没有“红”、“丝绒”、“礼服”,但模型“理解”了晚宴需要穿礼服,因此 ES 会高分返回“红色丝绒晚礼服”


🚀 进阶技巧:混合搜索 (Hybrid Search)

在实际电商场景中,向量搜索虽然懂语义,但有时候不够精确(比如搜具体的型号 SKU)。
最佳实践是:关键字搜索 + 向量搜索 混合使用。

在 ES 8.x 中,这非常简单,使用RRF (Reciprocal Rank Fusion)自动融合排名:

GET/products/_search{"knn":{"field":"product_vector","query_vector":[0.1,...],"k":10},"query":{"match":{"name":"晚礼服"}},"rank":{"rrf":{// 倒数排名融合算法"window_size":100,"rank_constant":20}}}

📝 总结

通过引入 Embedding 模型和 ES 的dense_vector,我们没有改动核心架构,没有引入新的重型数据库,就让搜索体验从“人工智障”进化到了“人工智能”。

  • 成本:几乎为 0(开源模型 + 现有 ES 集群)。
  • 收益:解决了长尾词搜索、语义鸿沟和跨模态搜索难题。

AI 时代,不要让你的搜索框还停留在 2010 年。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/22 6:09:15

2025年应届生转型指南:金融学转行AI,这些证书能帮你

作为金融学专业的应届生,如果想转行到AI领域,可能会感到迷茫,不知道从哪里开始。毕竟,课堂上学的大多是宏观经济、公司财务,和人工智能的算法、模型好像不太沾边。 其实,跨专业转型没有想象中那么难,关键是要找到一条清晰的学习路径。考取一些有含金量的证书,不仅能系…

作者头像 李华
网站建设 2026/6/20 0:52:18

Deepseek生成8088单板机的流水灯程序

1.Deepseek会话指令8位LED,端口地址800H,程序加载地址CS:IP 为0000:2000,用emu8086编写一流水灯程序2.DeppSeek生成的程序#make_bin#; BIN is plain binary format similar to .com format, but not limited to 1 segment; ; All values between # are d…

作者头像 李华
网站建设 2026/6/13 21:54:19

可靠运行的守护者:A5E45127009原厂配件的核心作用

在西门子罗宾康高压变频器的复杂架构中,每个指定编号的组件都承载着不可或缺的使命。A5E45127009作为经过原厂认证的关键备件,专为系统中特定的电路控制、信号隔离或电源管理功能而设计。其卓越的稳定性和精准的参数表现,是保障变频器整体性能…

作者头像 李华
网站建设 2026/6/19 12:17:23

ESP分区

电脑中的ESP分区是干什么的?UEFI(统一可扩展固件接口)与GPT(GUID分区表)的组合已成为现代计算机系统安装和启动的主流方式。然而,在这种新的安装方式下,一个名为“ESP分区”的组件显得尤为重要&…

作者头像 李华
网站建设 2026/6/20 11:20:24

规避交付风险,驱动生产效率:环形导轨选型核心逻辑与落地实施指南

摘要: 在自动化装配线、检测站及精密制造单元中,环形导轨系统已成为实现高效循环输送的关键基础设施。然而,一个常见的误区是仅关注导轨本身的品牌与价格,忽略了从设计源头到现场调试的全链路风险。本文旨在系统性地拆解环形导轨的…

作者头像 李华
网站建设 2026/6/19 10:12:39

vue3+vite mock引入使用

1、安装对应的包 npm install vite-plugin-mock mockjs -D2、配置 Vite vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue import { viteMockServe } from vite-plugin-mockexport default defineConfig({plugins: [vue(),viteMockServe({…

作者头像 李华