amazon-web-services - Elasticsearch-按多个数组中数组匹配的分数排序

标签 amazon-web-services elasticsearch elasticsearch-5 elasticsearch-aggregation amazon-elasticsearch

索引文件

{
  "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"] }
  ]
}

我有很多书有多页。每页都有一个单词列表。
我想搜索页面数量超过阈值的书籍。

阈值
  • min_word_match_score:2(两页之间words匹配的最低分数)
  • min_page_match_score:2(两本书之间的similar pages的最小数量)

  • 关键字
  • 相似的页面:两个页面至少具有min_word_match_score相同的单词
  • 相似的书:两本书至少具有min_page_match_score相似的页面

  • 预期结果

    根据指定的阈值,正确的返回值应该仅为book01,因为
  • book01-1和book_new-1的得分为2(> = min_word_match_score,totalScore ++)
  • book01-2和book_new-2的得分为2(> = min_word_match_score,totalScore ++)
  • book01和book_new的总得分为2(totalScore> = min_page_match_score)

  • 搜索查询不佳(不起作用)
    "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查询。

    该查询从本质上帮助您查找与相似的文档,该文档本身就是您将作为输入提供的

    基本上,算法是:

  • 从输入文档中找到tf-idf最高的前K个词。
  • 您可以从输入中指定单词的min_term_frequency应该为1或2,并在用例中将其为1。含义仅考虑输入文档中词频为1的那些词。
  • 根据这些术语或逻辑运算符
  • 构造N个析取查询
  • 这些N号可在查询请求中配置,默认情况下为25,属性为max_query_terms
  • 在内部执行查询并返回最相似的文档。

  • this link更准确地说,

    MLT查询只是从输入文档中提取文本,通常使用该字段中的同一分析器对其进行分析,然后选择tf-idf最高的前K个词构成这些词的析取查询。

    让我们看看如何实现您提到的一些用例。

    用例1:查找具有min_word_match_score 2的页面的文档。

    请注意,您的字段pages必须为 nested 类型。否则,使用 object 类型在这种情况下是不可能的。我建议您通过上述链接来了解更多信息。

    假设我有两个索引
  • my_book_index -这将在
  • 上搜索文档
  • my_book_index_input -将这些文档用作输入文档

  • 两者都将具有如下映射结构:
    {
      "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 14 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 --> ElasticsearchFor 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/

    相关文章:

    ElasticSearch - 通过嵌套字段上的嵌套聚合对聚合进行排序

    elasticsearch - Elasticsearch如何确定要查询的集群中的哪个节点

    elasticsearch - logstash索引文件多次?

    elasticsearch - 在Elasticsearch中跟踪哪些文档来自哪些分片

    java - 无法在 AWS lambda 函数中获取 AmazonDynamoDBClient

    node.js - 如何使用 AND & OR 编写 DynamoDB 查询过滤器?

    elasticsearch - “aggs”查询的输出结果不正确

    python - 如何使用 SSL 将 PySpark 连接到 Elasticsearch 并验证设置为 False 的证书?

    javascript - 如何使用 Meteor 上传文件到 Amazon S3?

    amazon-web-services - CloudFormation 模板不选择 key 对