【Elasticsearch】-实现向量相似检索

打印 上一主题 下一主题

主题 1051|帖子 1051|积分 3153

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
1、http请求方式

假如elasticsearch服务设置账号密码,则在请求的header中添加 Basic Auth 认证

请求方式:Post
请求地址:/index_name/_search
请求body:json格式
  1. {
  2. "size": 10, //返回条数
  3. "min_score": 0.8,  // 设置最低相似分值
  4. "_source": ["file_name", "length", "_es_doc_type"],  // 只返回指定字段
  5.   "query": {
  6.     "script_score": {
  7.       "query": {
  8.         "match_all": {}
  9.       },
  10.       "script": {
  11.             // _img_vector 为设置的向量索引字段
  12.         "source": "cosineSimilarity(params.query_vector, '_img_vector') + 0.0",
  13.         "params": {
  14.           "query_vector": [-1,1,-0.07559559,-0.007800484,0.11229578,0.064164124,....]
  15.         }
  16.       }
  17.     }
  18.   }
  19. }
复制代码
主要参数说明:
   

  • "from": 0, // 起始位置,0表现第一页
  • "size": 10, // 每页返回的记录数
  • "min_score": 0.5,   //最低相似度,最高1
  • "_source": ["image_id", "image_name", "image_vector"],   // 返回指定字段
  
返回结果如下:
  1. {
  2.         "took": 3,
  3.         "timed_out": false,
  4.         "_shards": {
  5.                 "total": 1,
  6.                 "successful": 1,
  7.                 "skipped": 0,
  8.                 "failed": 0
  9.         },
  10.         "hits": {
  11.                 "total": {
  12.                         "value": 1,
  13.                         "relation": "eq"
  14.                 },
  15.                 "max_score": 0.9014968,
  16.                 "hits": [
  17.                         {
  18.                                 "_index": "vedms",
  19.                                 "_type": "_doc",
  20.                                 "_id": "04a40e806be82e87f3c3a2f3877225bd.jpg",
  21.                                 "_score": 0.9014968,
  22.                                 "_source": {
  23.                                         "file_name": "04a40e806be82e87f3c3a2f3877225bd.jpg",
  24.                                         "_es_doc_type": "IMAGE",
  25.                                         "length": 89690
  26.                                 }
  27.                         }
  28.                 ]
  29.         }
  30. }
复制代码
需要确保传入的query_vector 长度一致性,前面的章节中以设定1024长度。
否则会出现如下错误:
   "reason": {
                      "type": "script_exception",
                      "reason": "runtime error",
                      "script_stack": [
                          "org.elasticsearch.xpack.vectors.query.ScoreScriptUtils$DenseVectorFunction.<init>(ScoreScriptUtils.java:74)",
                          "org.elasticsearch.xpack.vectors.query.ScoreScriptUtils$CosineSimilarity.<init>(ScoreScriptUtils.java:172)",
                          "cosineSimilarity(params.query_vector, '_img_vector') + 0.0",
                          "     
                      ],
                      "script": "cosineSimilarity(params.query_vector, '_img_vector') + 0.0",
                      "lang": "painless",
                      "position": {
                          "offset": 38,
                          "start": 0,
                          "end": 58
                      },
                      "caused_by": {
                          "type": "illegal_argument_exception",
                          "reason": "The query vector has a different number of dimensions [1023] than the document vectors [1024]."
                      }
                  }
  
2、Java调用脚本

SearchRequest  不允许在script设置 _source 属性内容,所以干脆将from、size、score一并拿出,只保留vector数据
_img_vector为前面界说的向量索引字段
  1. public List<Map<String, Object>> search(EsVectorSearchReq req) {
  2.         float[] vector = getImgFeature(req);
  3.         if (null == vector || vector.length == 0) {
  4.             return Collections.emptyList();
  5.         }
  6.         String queryJson = String.format(VECTOR_FORMAT, vectorToJson(vector));
  7.         log.debug("向量检索入参条件={}", queryJson);
  8.         Reader input = new StringReader(queryJson);
  9.         // 使用查询 DSL 进行搜索
  10.         SearchRequest searchRequest = new SearchRequest.Builder()
  11.                 .index(req.getIndexLib())
  12.                 .from(req.getFrom())
  13.                 .size(req.getSize())
  14.                 .minScore(req.getScore())
  15.                 .source(SourceConfig.of(src -> src
  16.                         .filter(SourceFilter.of(i -> i.includes(req.getColumns())))))
  17.                 .withJson(input)
  18.                 .build();
  19.         // 执行查询
  20.         List<Map<String, Object>> result = new ArrayList<>();
  21.         try {
  22.             SearchResponse<Map> searchResponse = esClient.search(searchRequest, Map.class);
  23.             // 输出结果
  24.             for (Hit<Map> hit : searchResponse.hits().hits()) {
  25.                 result.add(hit.source());
  26.             }
  27.             log.info("成功查询{}条", result.size());
  28.         } catch (IOException e) {
  29.             e.printStackTrace();
  30.         }
  31.         return result;
  32.     }
复制代码
  1. private String vectorToJson(float[] vector) {
  2.         StringBuilder sb = new StringBuilder("[");
  3.         for (int i = 0; i < vector.length; i++) {
  4.             sb.append(vector[i]);
  5.             if (i < vector.length - 1) {
  6.                 sb.append(",");
  7.             }
  8.         }
  9.         sb.append("]");
  10.         return sb.toString();
  11.     }
复制代码

  1. private static final String VECTOR_FORMAT = "{\n" +
  2.             "  "query": {\n" +
  3.             "    "script_score": {\n" +
  4.             "      "query": {\n" +
  5.             "        "match_all": {}\n" +
  6.             "      },\n" +
  7.             "      "script": {\n" +
  8.             "        "source": "cosineSimilarity(params.query_vector, 'img_vector') + 0.0",\n" +
  9.             "        "params": {\n" +
  10.             "          "query_vector": %s\n" +
  11.             "        }\n" +
  12.             "      }\n" +
  13.             "    }\n" +
  14.             "  }\n" +
  15.             "}";
复制代码
传入参数格式如下:
  1. {
  2.   "query": {
  3.     "script_score": {
  4.       "query": {
  5.         "match_all": {}
  6.       },
  7.       "script": {
  8.         "source": "cosineSimilarity(params.query_vector, '_img_vector') + 0.0",
  9.         "params": {
  10.           "query_vector": [-0.033....]
  11.         }
  12.       }
  13.     }
  14.   }
  15. }
复制代码

返回结果如下:
   {
    "_shards": {
        "failed": 0.0,
        "skipped": 0.0,
        "successful": 1.0,
        "total": 1.0
    },
    "hits": {
        "hits": [
            {
                "_id": "04a40e806be82e87f3c3a2f3877225bd.jpg",
                "_index": "vedms",
                "_score": 1.0,
                "_source": "{file_name=04a40e806be82e87f3c3a2f3877225bd.jpg}",
                "_type": "_doc"
            }
        ],
        "max_score": 1.0,
        "total": {
            "relation": "eq",
            "value": 1
        }
    },
    "timed_out": false,
    "took": 46
}
  

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

钜形不锈钢水箱

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表