基于浮点数组余弦相似度的ElasticSearch排序

kyxcudwk  于 2023-01-04  发布在  ElasticSearch
关注(0)|答案(2)|浏览(156)

是否可以根据两个不同浮点数组的余弦相似性进行排序?类似于通过传递一个坐标进行排序来根据地理距离进行排序?

vohkndzv

vohkndzv1#

如果数组之一是输入,则I是可能的,但您必须将余弦相似性实现为脚本:

"script": {
    "lang": "painless",
    "source": """
      def vector = params._source[params.vector_field];
      def dot_product = 0.0;
      def v_norm = 0.0;
      for (int i = 0; i < params.query_vector.length; ++i) { 
          def x = vector[i]; 
          dot_product += x * params.query_vector[i]; 
          v_norm += x * x;
      }
      return v_norm > 0 ? dot_product / (params.query_v_norm * Math.sqrt(v_norm)) : -1;
"""
  }

但是,这会使用字段source,这可能会很慢。See this other question to make it faster

kknvjkwl

kknvjkwl2#

此解决方案适用于ElasticSearch开放发行版(开放搜索)版本7.6.1:

GET jobsearch_v20/_search
{
  "size": 1,
  "query": {
    "script_score": {
      "query": {
        "match_all": {}
      },
      "script": {
        "lang": "painless",
        "source": """
        // def vector = params._source[params.field];
        def vector = [1,2,3]
        def dot_product = 0.0;
        def val_norm = 0.0;
        def vec_norm = 0.0;
        for (int i =0; i< params.query_value.length; ++i){
          def x = vector[i];
          dot_product += x * params.query_value[i];
          val_norm += x * x;
          vec_norm += params.query_value[i] * params.query_value[i];
          
        }
        return val_norm > 0 ? dot_product / (Math.sqrt(vec_norm) * Math.sqrt(val_norm)) : -1;
        """,
        "params": {
          "field": "vector",
          "query_value": [
            3,
            4,
            5
          ]
        }
      }
    }
  }
}

请将查询值替换为向量输入,并取消源代码后面的注解行的注解以运行它。它将对两个向量之间的相似性进行评分。

相关问题