如何在Elasticsearch中对Skills字段实现基于余弦相似度的语义搜索
实现基于余弦相似度的Skills字段语义搜索
要实现Skills字段的语义匹配(比如让"Communication"和"talking"这类语义相似的内容提升评分),你需要借助文本向量嵌入结合Elasticsearch的余弦相似度计算能力,替换原来的精确匹配逻辑,具体步骤如下:
1. 准备向量字段
首先要给索引添加一个用于存储Skills文本向量的字段,因为余弦相似度是基于向量计算的。假设我们新增skills_embedding字段,类型为dense_vector(维度根据你用的NLP模型确定,比如Sentence-BERT是768维):
PUT 2/_mapping { "properties": { "Skills": { "type": "text" }, "skills_embedding": { "type": "dense_vector", "dims": 768, "index": true, "similarity": "cosine" } } }
之后需要把已有的Skills文本转换成对应向量,存入skills_embedding字段——你可以在应用端用预训练NLP模型(比如Sentence-BERT)生成向量,再通过批量更新写入Elasticsearch;或者用Elasticsearch的预处理管道自动生成嵌入(需依赖对应插件)。
2. 修改查询实现语义匹配
替换原来的精确match过滤,改用script_score计算余弦相似度并加权,结合原有的Job_Group过滤逻辑:
GET 2/_search { "_source": ["Skills"], "query": { "function_score": { "query": { "match": { "Job_Group": "sales" } }, "functions": [ { "script_score": { "script": { "source": "cosineSimilarity(params.query_vector, doc['skills_embedding']) + 1", "params": { "query_vector": [/* 替换为查询词(如"Designation")对应的768维向量 */] } } }, "weight": 15 } ], "boost_mode": "sum" } } }
cosineSimilarity返回值范围是[-1,1],加1是为了将评分映射到[0,2]区间,避免负分拉低整体评分;boost_mode: sum会把Job_Group匹配的基础评分和语义匹配的评分相加,综合排序。
如果你的Elasticsearch是8.x及以上版本,也可以用更高效的近似最近邻(KNN)查询来实现:
GET 2/_search { "_source": ["Skills"], "query": { "bool": { "must": [ { "match": { "Job_Group": "sales" } }, { "knn": { "skills_embedding": { "vector": [/* 替换为查询词对应的向量 */], "k": 10, "similarity": "cosine" } } } ] } } }
注意事项
- 查询词的向量需要和Skills文本用同一个预训练模型生成,才能保证语义匹配的准确性;
- 如果不想自己处理向量生成,可以使用Elasticsearch官方的文本扩展插件(如Elastic Learned Sparse Encoder),直接基于文本做语义搜索,无需手动生成向量。
内容的提问来源于stack exchange,提问作者Vineet Vinayak
相关产品推荐
相关产品推荐

