elasticsearch - 弹性的全文和 knn_vector 混合搜索
问题描述
我目前正在研究一个搜索引擎,并且我已经开始实现语义搜索。我使用弹性的开放发行版,我的映射目前看起来像这样:
{
"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
}
}
}
}
}
}
问题是如果我在文档中没有这个词,那么它就不会被返回。例如,在第一个搜索查询中,当我搜索 trump(不在我的数据集中)时,我设法获取有关社交网络和政治的文档。混合搜索没有这些结果。
我试过这个:
{
"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"
}
}
}
推荐阅读
- angular - 如果总最小值不等于最大值则显示错误
- macos - Mac Gunzip 解压失败的不完整文件
- regex - 在 Perl 正则表达式中转义 @
- javascript - 如何使用 javascript 在 Django 模板中显示带有 html 元素值的警报框?
- javascript - 鼠标悬停时如何获得 figcaption 显示
- python - 如何从 Windows 读取 Linux 服务器上的文件?
- vba - 根据单元格值弹出VBA MsgBox
- java - PHP 上的 AJAX 请求示例?
- php - 服务器返回内容类型 application/x-httpd-php5 而不是 application/json
- java - 有谁知道如何在 Android Studio 中使用 Expression?