索引文件
{
"book_id":"book01",
"pages":[
{ "page_id":1, "words":["1", "2", "xx"] }
{ "page_id":2, "words":["4", "5", "xx"] }
{ "page_id":3, "words":["7", "8", "xx"] }
]
}
{
"book_id":"book02",
"pages":[
{ "page_id":1, "words":["1", "xx", "xx"] }
{ "page_id":2, "words":["4", "xx", "xx"] }
{ "page_id":3, "words":["7", "xx", "xx"] }
]
}
输入数据
{
"book_id":"book_new",
"pages":[
{ "page_id":1, "words":["1", "2", "3"] }
{ "page_id":2, "words":["4", "5", "6"] }
{ "page_id":3, "words":["xx", "xx", "xx"] }
]
}
我有很多书有多页。每页都有一个单词列表。
我想搜索页面数量超过阈值的书籍。
阈值
words
匹配的最低分数)similar pages
的最小数量)关键字
min_word_match_score
相同的单词min_page_match_score
相似的页面预期结果
根据指定的阈值,正确的返回值应该仅为
book01
,因为搜索查询不佳(不起作用)
"bool" : {
"should" : [
{
"match" : { "book_pages.visual_words" : {"query" : "1", "operator" : "OR"} },
"match" : { "book_pages.visual_words" : {"query" : "2", "operator" : "OR"} },
"match" : { "book_pages.visual_words" : {"query" : "3", "operator" : "OR"} }
}
],
"minimum_should_match" : 2
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
如果页面查询匹配,我首先尝试做一个部分,但不是逐数组搜索,而是针对所有页面的单词进行搜索。而且我不太确定如何管理两个不同的分数-单词匹配得分和页面匹配得分。
我应该深入研究innerHit吗?请帮忙!
最佳答案
不是最好的,但我的两分钱!
我不认为Elasticsearch可以针对此用例提供确切的解决方案。执行所需操作的最接近方法是利用More Like This查询。
该查询从本质上帮助您查找与相似的文档,该文档本身就是您将作为输入提供的。
基本上,算法是:
1
。含义仅考虑输入文档中词频为1
的那些词。 25
,属性为max_query_terms
从this link更准确地说,
MLT查询只是从输入文档中提取文本,通常使用该字段中的同一分析器对其进行分析,然后选择tf-idf最高的前K个词构成这些词的析取查询。
让我们看看如何实现您提到的一些用例。
用例1:查找具有min_word_match_score 2的页面的文档。
请注意,您的字段
pages
必须为 nested
类型。否则,使用 object
类型在这种情况下是不可能的。我建议您通过上述链接来了解更多信息。假设我有两个索引
两者都将具有如下映射结构:
{
"mappings": {
"properties": {
"book_id":{
"type": "keyword"
},
"pages":{
"type": "nested"
}
}
}
}
my_book_index的样本文档:
POST my_book_index/_doc/1
{
"book_id":"book01",
"pages":[
{ "page_id":1, "words":["11", "12", "13", "14", "105"] },
{ "page_id":2, "words":["21", "22", "23", "24", "205"] },
{ "page_id":3, "words":["31", "32", "33", "34", "305"] },
{ "page_id":4, "words":["41", "42", "43", "44", "405"] }
]
}
POST my_book_index/_doc/2
{
"book_id":"book02",
"pages":[
{ "page_id":1, "words":["11", "12", "13", "104", "105"] },
{ "page_id":2, "words":["21", "22", "23", "204", "205"] },
{ "page_id":3, "words":["301", "302", "303", "304", "305"] },
{ "page_id":4, "words":["401", "402", "403", "404", "405"] }
]
}
POST my_book_index/_doc/3
{
"book_id":"book03",
"pages":[
{ "page_id":1, "words":["11", "12", "13", "100", "105"] },
{ "page_id":2, "words":["21", "22", "23", "200", "205"] },
{ "page_id":3, "words":["301", "302", "303", "300", "305"] },
{ "page_id":4, "words":["401", "402", "403", "400", "405"] }
]
}
my_book_index_input的样本文档:
POST my_book_index_input/_doc/1
{
"book_id":"book_new",
"pages":[
{ "page_id":1, "words":["11", "12", "13", "14", "15"] },
{ "page_id":2, "words":["21", "22", "23", "24", "25"] }
]
}
更喜欢此查询:
用例:基本上,我感兴趣的是查找类似于上述具有
4 matches in page 1
或4 matches in page 2
的文档的文档POST my_book_index/_search
{
"size": 10,
"_source": "book_id",
"query": {
"nested": {
"path": "pages",
"query": {
"more_like_this" : {
"fields" : ["pages.words"],
"like" : [
{
"_index": "my_book_index_input",
"_id": 1
}
],
"min_term_freq" : 1,
"min_doc_freq": 1,
"max_query_terms" : 25,
"minimum_should_match": 4
}
},
"inner_hits": {
"_source": ["pages.page_id", "pages.words"]
}
}
}
}
基本上,我想在
my_book_index
中搜索与索引_doc:1
中的my_book_index_input
相似的所有文档。注意查询中的每个参数。我建议您逐行了解所有这些内容。
执行该查询时,请注意以下响应:
响应:
{
"took" : 71,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 6.096043,
"hits" : [
{
"_index" : "my_book_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 6.096043,
"_source" : {
"book_id" : "book01" <---- Document 1 returns
},
"inner_hits" : {
"pages" : {
"hits" : {
"total" : {
"value" : 2, <---- Number of pages hit for this document
"relation" : "eq"
},
"max_score" : 6.096043,
"hits" : [
{
"_index" : "my_book_index",
"_type" : "_doc",
"_id" : "1",
"_nested" : {
"field" : "pages",
"offset" : 0
},
"_score" : 6.096043,
"_source" : {
"page_id" : 1, <---- Page 1 returns as it has 4 matches
"words" : [
"11",
"12",
"13",
"14",
"105"
]
}
},
{
"_index" : "my_book_index",
"_type" : "_doc",
"_id" : "1",
"_nested" : {
"field" : "pages",
"offset" : 1
},
"_score" : 6.096043,
"_source" : {
"page_id" : 2, <--- Page 2 returns as it also has 4 matches
"words" : [
"21",
"22",
"23",
"24",
"205"
]
}
}
]
}
}
}
}
]
}
}
请注意,仅返回book_id:1的文档。原因很简单。我在查询中提到了以下属性:
"min_term_freq" : 1,
"min_doc_freq": 1,
"max_query_terms" : 25,
"minimum_should_match": 4
基本上,仅考虑从术语freq为1的输入文档中搜索的那些术语,该术语在最少1个文档中可用,并且在一个嵌套文档中的匹配数应为4。
更改参数,例如将
min_doc_freq
转换为3
,将min_should_match
转换为3
,您应该会看到更多文档。注意,由于实现方式的原因,您不会看到所有具有上述属性的文档。记住我一开始提到的步骤。也许就是这个原因。
用例2:用例1 +仅返回
min page match
为2的那些我不确定是否支持该功能,即
adding filter to inner_hits based on _count of inner_hits
,但是我相信这是可以在应用程序层添加的功能。基本上得到上述响应,计算inner_hits.pages.hits.total_value
,从而仅将这些文档进一步退还给使用者。基本上,以下是您的请求响应流程:For Request: Client Layer (UI) ---> Service Layer --> Elasticsearch
For Response: Elasticsearch ---> Service Layer (filter logic for n pages match) --> Client Layer (or UI)
这可能不是最好的解决方案,有时可能会给您带来与您期望的结果不符的结果,但是我建议至少尝试一下,作为唯一的其他解决方案而不是使用此查询,这令人遗憾您自己的自定义客户端代码,该代码将使用TermVectorAPI中提到的this link。
记住算法是MLT查询的工作原理,并查看您是否可以深入了解结果返回结果的方式。
不确定是否可以,但是希望对您有所帮助!
关于amazon-web-services - Elasticsearch-按多个数组中数组匹配的分数排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60734073/