【问题标题】:Tweaking relevance score of only certain queries仅调整某些查询的相关性分数
【发布时间】:2019-08-05 14:10:54
【问题描述】:

我有一个用例,当用户根据术语搜索某些搜索词时,我需要从该搜索词的总结果中对某些文档进行排名。

到目前为止我所尝试的:

我已将嵌套字段 tuning 添加到索引上将具有这些自定义提升的文档。

{
    _id: 1234,
    'name': 'Fancy potato masher',
    'tuning': [
        {'term': 'potato', 'rank': 5},
        {'term': 'masher', 'rank': 10}, 
    ]
},
{
    _id: 2345,
    'name': 'Decent potato masher',
    'tuning': [
        {'term': 'potato', 'rank': 3},
        {'term': 'masher', 'rank': 7},
    ]
},
{
    _id: 3456,
    'name': 'Useless potato masher',
    'tuning': [
        {'term': 'potato', 'rank': -5},
        {'term': 'masher', 'rank': -7},
    ]
},
{
    _id: 4567,
    'name': 'Ordinary potato masher',
    'tuning': []
}

所以在这里当我们搜索potatomasher 时,我希望结果按1234, 2345, 4567, 3456 的顺序排列。

我的sort 部分查询如下所示:

{
    'sort': {
        'tuning.rank' => {
            'order' => 'desc',
            'nested' => {
                'path' => 'tuning',
                'filter' => {
                    'match' => {
                        'tuning.term' => 'potato'
                    }
                }

            }
        },
    }
}

我的结果按1234, 2345, 3456, 4567 的顺序排列。所以基本上任何缺少tuning 数据的东西都会出现在最后,而不是那些排名为负的。

如何正常解决这个问题,而不需要花哨的学习排名等。

【问题讨论】:

    标签: elasticsearch lucene


    【解决方案1】:

    只需添加missing 参数,如下例所示。

    另请注意,您使用nested_filternested_path 的方式已被弃用,如此link 帖子ES 6.2 版本中所述。

    我已经提到了如何使用最新和已弃用的 DSL 来获得您想要的东西。根据您使用的版本随意使用。

    查询 pre ES 6.2 版本

    POST <your_index_name>/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match_all": {}      //query logic as per your requirement
            }
          ]
        }
      },
      "sort": [
        {
          "tuning.rank": {
            "order": "desc",
            "nested_path": "tuning",
            "nested_filter": {
                "match": {
                  "tuning.term": "potato"
                }
            },
            "missing": "0"                    <------ Note this.
          }
        }
      ]
    }
    

    在上面的查询中,只关注排序逻辑,我刚刚添加了missing参数,值为0,这意味着如果字段tuning.term缺失,让排序值为@987654330 @ 以便对文档进行相应的排序。

    查询 ES 6.2+ 版本

    POST <your_index_name>/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match_all": {}
            }
          ]
        }
      },
      "sort":[
        {
          "tuning.rank":{
            "order": "desc",
            "nested":{
              "path": "tuning",
              "filter":{
                "match":{
                  "tuning.term": "potato"
                }
              }
            },
            "missing": "0"
          }
        }
      ]
    }
    

    以下是响应在我的机器中的显示方式:

    回应:

    {
      "took" : 3,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 4,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [
          {
            "_index" : "someindex",
            "_type" : "_doc",
            "_id" : "1234",
            "_score" : null,
            "_source" : {
              "name" : "Fancy potato masher",
              "tuning" : [
                {
                  "term" : "potato",
                  "rank" : 5
                },
                {
                  "term" : "masher",
                  "rank" : 10
                }
              ]
            },
            "sort" : [
              5
            ]
          },
          {
            "_index" : "someindex",
            "_type" : "_doc",
            "_id" : "2345",
            "_score" : null,
            "_source" : {
              "name" : "Decent potato masher",
              "tuning" : [
                {
                  "term" : "potato",
                  "rank" : 3
                },
                {
                  "term" : "masher",
                  "rank" : 7
                }
              ]
            },
            "sort" : [
              3
            ]
          },
          {
            "_index" : "someindex",
            "_type" : "_doc",
            "_id" : "4567",
            "_score" : null,
            "_source" : {
              "name" : "Ordinary potato masher",
              "tuning" : [ ]
            },
            "sort" : [
              0
            ]
          },
          {
            "_index" : "someindex",
            "_type" : "_doc",
            "_id" : "3456",
            "_score" : null,
            "_source" : {
              "name" : "Fancy potato masher",
              "tuning" : [
                {
                  "term" : "potato",
                  "rank" : -5
                },
                {
                  "term" : "masher",
                  "rank" : -7
                }
              ]
            },
            "sort" : [
              -5
            ]
          }
        ]
      }
    }
    

    现在,如果您运行查询,您的结果将被相应地排序。

    更新的相关性答案:

    您在上面看到我正在使用自定义排序,因此,相关性不会显示出来。

    默认情况下,如果您不使用任何排序逻辑,则结果按相关性排序,您将能够查看_score 值。

    另外请注意,我使用的是 match_all,它会给每个文档打 1 分。因此,如果您删除排序逻辑,您将在我共享的查询中返回所有得分为 1 的文档。

    相关性是一个复杂的话题,很大程度上取决于您的用例。我建议您花一些时间研究function_score 查询,以便您了解如何影响分数。稍微玩一下,你就会慢慢开始理解它是如何工作的。

    至于您的评论,如果您还想显示或显示 _score,您只需在排序逻辑中添加 _score 字段即可。所以首先,它会根据tuning.rank 对文档进行排序,然后根据_score 对文档进行排序。

    下面是它的完成方式。

    POST <your_index_name>/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match_all": {}
            }
          ]
        }
      },
      "sort":[
        {
          "tuning.rank":{
            "order": "desc",
            "nested":{
              "path": "tuning",
              "filter":{
                "match":{
                  "tuning.term": "potato"
                }
              }
            },
            "missing": "0"
          }
        },
        {
          "_score": { "order": "desc" }
        }
      ]
    }
    

    回应:

    {
      "took" : 2,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 4,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [
          {
            "_index" : "someindex",
            "_type" : "_doc",
            "_id" : "1234",
            "_score" : 1.0,
            "_source" : {
              "name" : "Fancy potato masher",
              "tuning" : [
                {
                  "term" : "potato",
                  "rank" : 5
                },
                {
                  "term" : "masher",
                  "rank" : 10
                }
              ]
            },
            "sort" : [
              5,
              1.0
            ]
          },
          {
            "_index" : "someindex",
            "_type" : "_doc",
            "_id" : "2345",
            "_score" : 1.0,
            "_source" : {
              "name" : "Decent potato masher",
              "tuning" : [
                {
                  "term" : "potato",
                  "rank" : 3
                },
                {
                  "term" : "masher",
                  "rank" : 7
                }
              ]
            },
            "sort" : [
              3,
              1.0
            ]
          },
          {
            "_index" : "someindex",
            "_type" : "_doc",
            "_id" : "4567",
            "_score" : 1.0,
            "_source" : {
              "name" : "Ordinary potato masher",
              "tuning" : [ ]
            },
            "sort" : [
              0,
              1.0
            ]
          },
          {
            "_index" : "someindex",
            "_type" : "_doc",
            "_id" : "3456",
            "_score" : 1.0,
            "_source" : {
              "name" : "Fancy potato masher",
              "tuning" : [
                {
                  "term" : "potato",
                  "rank" : -5
                },
                {
                  "term" : "masher",
                  "rank" : -7
                }
              ]
            },
            "sort" : [
              -5,
              1.0
            ]
          }
        ]
      }
    }
    

    此外,为了让您可以看到相关性文档不是按相关性排序而是根据您的排序逻辑排序,请尝试运行以下查询:

    POST <your_index_name>/_search
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "name": "potato decent"
              }
            }
          ]
        }
      },
      "sort":[
        {
          "tuning.rank":{
            "order": "desc",
            "nested":{
              "path": "tuning",
              "filter":{
                "match":{
                  "tuning.term": "potato"
                }
              }
            },
            "missing": "0"
          }
        },
        {
          "_score": { "order": "desc" }
        }
      ]
    }
    

    您可以在结果中看到,具有较高 _score 值的文档仍然会出现在较低的位置,因为我们主要基于 tuning.rank 进行排序。

    希望对你有帮助!

    【讨论】:

    • 谢谢@Kamal,现在效果更好了。有没有办法让_score 也填充?它目前为 NULL。这是否会影响记录的相关性而不以任何方式进行调整?
    • @Deepak 我已经更新了我的答案。如果您有任何疑问,请查看并告诉我。
    • 太棒了!这很有意义。如果我在排序逻辑中包含_score,它会给我一个错误No enum constant org.elasticsearch.search.sort.SortOrder._SCORE,您可以帮助我解决这个问题,或者我可以提出一个新问题来解决这个问题。您还认为我应该使用function_score 而不是在sort 中添加逻辑吗?
    • @Deepak,我建议你开始一个新问题。这对于有类似问题的其他人也很有用。请完整提及您的用例。对于错误,请仔细注意我是如何在上面添加 _score 的。 "_score": { "order": "desc" }
    • 谢谢,我现在就结束这个问题。 :)
    猜你喜欢
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多