使用Elasticsearch实现矢量数据存储和搜索

@TOC[1]
目录如下:
- • 1.简介
- • 2.实验前的准备工作❀1.设置向量字段
- • 2.2 写入数据
- • 3.2 曼哈顿 3 乘积:距离:l1norm
- • 3.4欧氏距离:l2norm
- • 3.5 自定义计算功能
矢量数据库:利用Elasticsearch实现矢量数据存储和搜索
1.简介
Elasticsearch 7.x 版本支持向量检索[2]。在向量函数的计算过程中,对所有匹配文档执行线性扫描。因此,预期查询时间随着匹配文档的数量线性增加。为此,建议使用查询参数来限制匹配文档的数量(类似于二次检索的逻辑,先使用匹配查询检索相关文档,然后使用向量函数计算文档相关性)。
访问 dense_vector
的推荐方法是使用 cosinesimilarity、dotProduct、1norm 或 l2norm 函数。但请注意,每个 DSL 脚本只能调用这些函数一次。例如,不要在循环中使用这些函数来计算文档向量与其他几个向量之间的相似度。如果需要此功能,可以通过直接访问向量值来重新实现这些功能。 ?
// 7.x 支持的 dims 最大为 1024。
PUT index3
{
"mappings": {
"properties": {
"my_vector": {
"type": "dense_vector",
"dims": 3
},
"my_text" : {
"type" : "keyword"
}
}
}
}
2.2 写入数据
PUT index3/_doc/1
{
"my_text" : "text1",
"my_vector" : [0.5, 10, 6]
}
PUT index3/_doc/2
{
"my_text" : "text2",
"my_vector" : [-0.5, 10, 10]
}
3. 向量计算函数
3.1 余弦相似度:cosineSimilarity
余弦相似度函数计算给定文档的向量度量之间的余弦相似度向量的度量。
POST index3/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source": "cosineSimilarity(params.queryVector, doc['my_vector'])+1.0",
"params": {
"queryVector": [-0.5, 10, 6]
}
}
}
}
}
- 1。必须指定过滤器(查询)来限制
script_score
计算的文档数量。 - 2。
脚本
为了避免负分数,脚本将 1.0 添加到余弦相似度
。 - 3。为了更好地利用 DSL 优化器,您可以使用参数指定查询向量。
- 4。检查缺失值:如果文档中没有用于执行向量函数的向量场的值,则会显示错误消息。您可以使用
doc['my_vector'].size() == 0
来检查文档的字段my_Putyin
中是否有值。脚本示例:
"source":
"
doc['my_vector'].size() == 0 ? 0 :
cosineSimilarity(params.queryVector, 'my_vector')
"
如果文档的字段dense_vector
与查询的向量维度不同,系统会抛出异常。
3.2 计算点积:dotProduct
dotProduct 函数计算给定查询向量和文档向量之间的点积度量。
POST index3/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source": """
double value = dotProduct(params.queryVector,doc['my_vector']);
return sigmoid(1, Math.E, -value);
""",
"params": {
"queryVector": [
-0.5,
10,
6
]
}
}
}
}
}
- 1。使用正常的
sigmoid
函数以避免负分数。
3.3 曼哈顿距离:l1norm
l1norm
该函数计算给定查询向量和文档向量之间的 L1 距离(曼哈顿距离)。
POST index3/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source":"1 / (1 + l1norm(params.queryVector, doc['my_vector']))",
"params": {
"queryVector": [-0.5, 10, 6]
}
}
}
}
}
- 1。与表示相似性的余弦相似度不同,
1norm
和l2norm
表示距离或差异。这意味着向量越相似,1norm
和l2norm
的得分越低。因此,如果我们需要类似的向量来获得更高的分数,我们可以反转1norm
和l2norm
的输出。此外,为了避免当文档向量与查询完全匹配时被零除,分母上加 1。
3.4 欧氏距离:l2norm
l2norm 函数计算给定查询向量和文档向量之间的 L2 距离(欧氏距离)。
POST index3/_search
{
"query": {
"script_score": {
"query": {
"match_all": {}
},
"script": {
"source": "1 / (1 + l2norm(params.queryVector, doc['my_vector']))",
"params": {
"queryVector": [
-0.5,
10,
6
]
}
}
}
}
}
3.5 自定义计算功能
使用此功能可以访问向量的值并自定义向量余弦相似度计算。从 Elasticsearch 7.8.0 开始,ES 就支持向量 getter 函数 doc[].vectorValue,但在 ES 7.5.1 或 7.8.0 以下版本中失败。
可以通过以下函数直接访问向量值:
- •
doc[].vectorValue
– 以浮点数组形式返回向量值。 - •
doc[].magnitude
- 以浮点形式返回向量的幅值(对于版本 7.5 之前创建的向量,不会存储向量的幅值)。所以这个函数每次调用都会重新计算。? https://github.com/elastic/elasticsearch/blob/e8c382f89553e3a7aaafa88a5934288c1192acdc/docs/reference/vector-s/vector-functions.asciidoc❀
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。