全文和 knn_vector 混合搜索 elastic

full-text and knn_vector hybrid search for elastic

我目前正在研究一个搜索引擎,我已经开始实施语义搜索。我使用 elastic 的 open distro 版本,目前我的映射看起来像这样:

{
  "settings": {
    "index": {
      "knn": true,
      "knn.space_type": "cosinesimil"
    }
  },
  "mappings": {
    "properties": {
      "title": { 
        "type" : "text"
      },
      "data": { 
        "type" : "text"
      },
      "title_embeddings": {
        "type": "knn_vector", 
        "dimension": 600
      },
      "data_embeddings": {
        "type": "knn_vector", 
        "dimension": 600
      }
    }
  }
}

对于基本 knn_vector 搜索我使用这个 :

{
  "size": size,
  "query": {
    "script_score": {
      "query": {
        "match_all": { }
      },
      "script": {
        "source": "cosineSimilarity(params.query_value, doc[params.field1]) + cosineSimilarity(params.query_value, doc[params.field2])",
        "params": {
          "field1": "title_embeddings",
          "field2": "data_embeddings",
          "query_value": query_vec
        }
      }
    }
  }
}

而且我已经设法通过这种方式进行了一种混合搜索:

{
  "size": size,
  "query": {
    "function_score": {
      "query": {
        "multi_match": { 
          "query": query,
          "fields": ["data", "title"]
        }
      },
      "script_score": {
        "script": {
          "source": "cosineSimilarity(params.query_value, doc[params.field1]) + cosineSimilarity(params.query_value, doc[params.field2])",
          "params": {
            "field1": "title_embeddings",
            "field2": "data_embeddings",
            "query_value": query_vec
          }
        }
      }
    }
  }
}

问题是如果我在文档中没有这个词,那么它就不会被退回。例如,在第一个搜索查询中,当我搜索王牌(不在我的数据集中)时,我设法获得了有关社交网络和政治的文档。我没有使用混合搜索得到这些结果。

我已经试过了:

 {
  "size": size,
  "query": {
    "function_score": {
      "query": {
        "match_all": { }
      },
      "functions": [
      {
        "filter" : {
          "multi_match": { 
            "query": query,
            "fields": ["data", "title"]
          }
        },
        "weight": 1
      },
      {
        "script_score" : {
          "script" : {
            "source": "cosineSimilarity(params.query_value, doc[params.field1]) + cosineSimilarity(params.query_value, doc[params.field2])",
            "params": {
              "field1": "title_embeddings",
              "field2": "data_embeddings",
              "query_value": query_vec
            }
          }
        },
        "weight": 4
      }
      ],
      "score_mode": "sum",
      "boost_mode": "sum"
    }
  }
}

但是多重匹配部分为所有匹配的文档提供了一个恒定的分数,我想使用过滤器对我的文档进行排名,就像在正常的全文查询中一样。有什么想法吗?或者我应该使用另一种策略?提前谢谢你。

在 Archit Saxena 的帮助下,这里解决了我的问题:

{
  "size": size,
  "query": {
    "function_score": {
      "query": {
        "bool": { 
          "should" : [
            {
              "multi_match" : { 
                "query": query,
                "fields": ["data", "title"]
              }
            },
            {
              "match_all": { }
            }
          ],
          "minimum_should_match" : 0
        }
      },
      "functions": [
      {
        "script_score" : {
          "script" : {
            "source": "cosineSimilarity(params.query_value, doc[params.field1]) + cosineSimilarity(params.query_value, doc[params.field2])",
            "params": {
              "field1": "title_embeddings",
              "field2": "data_embeddings",
              "query_value": query_vec
            }
          }
        },
        "weight": 20
      }
      ],
      "score_mode": "sum",
      "boost_mode": "sum"
    }
  }
}