创建数据
POST product- index/ _bulk? refresh= true
{ "index" : { "_id" : "1" } }
{ "product-vector" : [ 230.0 , 300.33 , - 34.8988 , 15.555 , - 200.0 ] , "price" : 1599 }
{ "index" : { "_id" : "2" } }
{ "product-vector" : [ - 0.5 , 100.0 , - 13.0 , 14.8 , - 156.0 ] , "price" : 799 }
{ "index" : { "_id" : "3" } }
{ "product-vector" : [ 0.5 , 111.3 , - 13.0 , 14.8 , - 156.0 ] , "price" : 1099 }
...
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
使用search
API运行包含向量函数
的script_score
查询。 向量函数的类型有:
cosineSimilarity
-计算余弦相似度dotProduct
-计算点积l1 norm
-计算L1距离Hamming
-计算Hamming距离l2 norm
-计算L2距离doc[].vectorValue
-以浮点数组的形式返回向量的值doc[].magnitude
-返回向量的大小 接下来以cosineSimilarity
为例,这是一个通过计算两个向量的余弦大小来判断向量相似度的函数。我们通过传入的参数向量queryVector
,这个名称是自定义的,但是需要与source
的脚本中params.queryVector
一致,下面方法将会查询所有文档
POST product- index/ _search
{
"query" : {
"script_score" : {
"query" : {
"match_all" : { }
} ,
"script" : {
"source" : "cosineSimilarity(params.queryVector, 'product-vector') + 1.0" ,
"params" : {
"queryVector" : [ - 0.5 , 90.0 , - 10 , 14.8 , - 156.0 ]
}
}
}
}
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">
但是使用match_all
查询来全量匹配所有文档会显著增加搜索延迟,为了限制传递给vector
函数的匹配文档的数量,可以在script_score.query
参数中指定一个过滤查询。例如下面示例:
POST product- index/ _search
{
"query" : {
"script_score" : {
"query" : {
"bool" : {
"filter" : {
"range" : {
"price" : {
"gte" : 1000
}
}
}
}
} ,
"script" : {
"source" : "cosineSimilarity(params.queryVector, 'product-vector') + 1.0" ,
"params" : {
"queryVector" : [ - 0.5 , 90.0 , - 10 , 14.8 , - 156.0 ]
}
}
}
}
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
2.3 两种搜索的对比
原理差异
精确暴力搜索:在进行搜索时,精确暴力搜索会遍历数据集中的每一个向量,逐一计算查询向量与它们之间的相似度(如欧几里得距离、余弦相似度等),然后根据相似度的大小对所有向量进行排序,最后选取最相似的k
个向量作为结果返回。这种方法简单直接,能够保证搜索结果的精确性,但在数据量较大时,计算量会非常庞大。 近似 k - NN 搜索:近似 k - NN 搜索则采用了一些优化策略来减少计算量。例如,利用上述提到的 KD - Tree、HNSW 等索引结构,通过构建数据的层次化表示或图结构,在搜索时能够快速定位到可能包含相似向量的区域,而无需遍历整个数据集。以 HNSW 为例,它通过多层图结构,在高层图中快速跳过大量不相关的向量,仅在底层图中对局部区域进行更精确的搜索,从而在保证一定搜索精度的前提下,大大提高了搜索效率。
性能表现
搜索时间:精确暴力搜索的搜索时间与数据集的大小成正比,数据量越大,搜索时间越长。在大规模数据集上,搜索可能需要很长时间才能完成。而近似 k - NN 搜索借助索引结构,能够显著减少搜索过程中需要计算相似度的向量数量,搜索时间相对较短,尤其在处理海量数据时,优势更为明显。 内存使用:精确暴力搜索不需要额外的内存来存储索引结构,仅需存储数据集本身。然而,近似 k - NN 搜索需要构建和维护索引结构,这会占用额外的内存空间。例如,HNSW 索引在构建过程中会生成多层图结构,每个节点都需要存储一定的连接信息,因此会消耗更多的内存。
适用场景
精确暴力搜索:适用于数据集较小、对搜索结果的精确性要求极高且对搜索时间没有严格限制的场景。例如,在一些数据量有限的科研项目中,研究人员可能更关注搜索结果的准确性,而不太在意搜索时间,此时精确暴力搜索可以满足需求。 近似 k - NN 搜索:在实际应用中,尤其是面对大规模数据集时,近似 k - NN 搜索更为适用。例如,在图像搜索引擎中,可能需要处理数百万甚至数十亿张图像的向量数据,如果使用精确暴力搜索,搜索效率将极低。而近似 k - NN 搜索能够在较短的时间内返回近似最优的结果,满足用户对实时性的需求
用精确搜索的情况
公司只有200份合同,需要100%确保找到所有相关文件 医疗诊断系统,不能容忍任何漏诊可能
用近似搜索的情况
淘宝有10亿商品图片,用户想快速找到相似款衣服 抖音推荐视频,允许少量误差但要求毫秒级响应
精确的强力kNN保证了准确的结果,但无法很好地扩展大型数据集。如果必须要使用精确暴力搜索,您可以通过使用查询参数来限制传递给函数的匹配文档的数量。如果过滤数据到一个小的文档子集,就可以得到很好的搜索结果。
三、Elasticsearch支持的其他语义搜索方式
Elasticsearch使用自然语言处理(NLP)和向量搜索提供各种语义搜索功能。使用NLP模型使您能够从文本中提取文本嵌入。嵌入是提供文本的数字表示的向量。具有相似含义的内容片段具有相似的表示。
Elasticsearch中的semantic_text
字段也支持语义文本搜索。在使用时只需要将文档的字段设置为semantic_text
, 不需要指定如何为数据生成嵌入,或者如何对其进行索引。推理端点自动确定要使用的嵌入生成,索引和查询。
翻译 警告:此功能处于测试阶段,可能会发生变化。设计和代码不如官方GA功能成熟,并且按原样提供,没有任何保证。Beta版功能不受正式GA功能的支持SLA的限制。使用时需要注意风险
使用
创建Index Mapping 默认是使用预配置的.elser-2-elasticsearch
端点,使用以下API请求设置semantic_text
:
PUT semantic- embeddings
{
"mappings" : {
"properties" : {
"content" : {
"type" : "semantic_text"
}
}
}
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
加载数据 将文档添加到索引时,Elasticsearch 会自动使用指定的推理端点计算嵌入,并将其存储在 semantic_text
字段中。您无需手动生成嵌入向量。以下是索引文档的示例:
PUT semantic- embeddings/ _doc/ 1
{
"content" : "Elasticsearch 8.17 introduces semantic search capabilities."
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
语义搜索
GET semantic- embeddings/ _search
{
"query" : {
"semantic" : {
"field" : "content" ,
"query" : "如何在跑步时避免肌肉酸痛?"
}
}
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
使用嵌入丰富数据集之后,可以使用语义搜索查询数据。在语义查询类型中提供semantic_text
字段名称和查询文本。用于为semantic_text
字段生成嵌入的推理端点将用于处理查询文本。
通过上述步骤,您可以在 Elasticsearch 8.17 中利用 semantic_text
字段实现高效的语义搜索功能。该功能使搜索更加智能,能够理解查询的意图和上下文,从而提供更相关的搜索结果。
向量搜索典型应用场景
基于自然语言处理(NLP)算法的相关性排序 产品推荐和推荐引擎 图像或视频的相似性搜索
data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/qq2632246528/article/details/145972016","extend1":"pc","ab":"new"}">>
id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type1" id="blog_extension">
class="blog_extension_card" data-report-click="{"spm":"1001.2101.3001.6470"}" data-report-view="{"spm":"1001.2101.3001.6470"}">
class="blog_extension_card_left">
class="blog_extension_card_cont">
class="blog_extension_card_cont_l">
程序员大任
class="blog_extension_card_cont_r">
微信公众号
程序员大任,分享知识~
评论记录:
回复评论: