首页 > 解决方案 > 仅调整某些查询的相关性分数

问题描述

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

到目前为止我已经尝试过:

我已经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': []
}

所以在这里当我们搜索potatoor时masher,我希望结果的顺序是1234, 2345, 4567, 3456

sort的部分查询如下所示:

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

            }
        },
    }
}

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

这个问题如何在不花哨的学习排名等的情况下正常解决。

标签: elasticsearchlucene

解决方案


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

另请注意,您使用的方式nested_filternested_path被弃用,如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丢失,让排序值成为0文档将相应地排序。

查询 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.

希望能帮助到你!


推荐阅读