Code前端首页关于Code前端联系我们

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

terry 2年前 (2023-09-26) 阅读数 70 #后端开发
使用Elasticsearch实现向量数据存储与搜索

@TOC[1]

目录如下:

  • • 1.简介
  • • 2.实验前的准备工作❀1.设置向量字段
  • • 2.2 写入数据
  • • 3. 向量计算功能
  • • 3.1 余弦相似度:cosineSimilarity
    • • 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. 1。必须指定过滤器(查询)来限制 script_score 计算的文档数量。
    2. 2。 脚本为了避免负分数,脚本将 1.0 添加到 余弦相似度
    3. 3。为了更好地利用 DSL 优化器,您可以使用参数指定查询向量。
    4. 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. 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. 1。与表示相似性的余弦相似度不同,1norml2norm 表示距离或差异。这意味着向量越相似,1norml2norm 的得分越低。因此,如果我们需要类似的向量来获得更高的分数,我们可以反转 1norml2norm 的输出。此外,为了避免当文档向量与查询完全匹配时被零除,分母上加 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前端网发表,如需转载,请注明页面地址。

    发表评论:

    ◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

    热门