大数据利器Elasticsearch之dis_max查询

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战markdown

本Elasticsearch相关文章的版本为:7.4.2elasticsearch

图书馆收藏了一些书籍,相关信息存储在book索引内,下面是两个文档信息:post

POST /book/_doc/1
{
  "body": "elasticsearch filter",
  "title": "elasticsearch basic query"
}
复制代码
POST /book/_doc/2
{
  "body": "single value search",
  "title": "elasticsearch aggs query"
}
复制代码

小明同窗想查询elasticsearch聚合查询方面相关的知识: 若是使用should对body和title进行match查询:spa

POST /book/_search
{
  "query": {
    "bool": {
      "should": [
        {"match": {"body": "elasticsearch aggs"}},
        {"match": {"title": "elasticsearch aggs"}}
        ]
    }
  }
}
复制代码

你会以为文档2会更符合小明的须要,可是返回的查询结果的相关性得分缺失文档1高于文档2:code

{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.9372343,
    "hits" : [
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.9372343,
        "_source" : {
          "body" : "elasticsearch filter",
          "title" : "elasticsearch basic query"
        }
      },
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.87546873,
        "_source" : {
          "body" : "single value search",
          "title" : "elasticsearch aggs query"
        }
      }
    ]
  }
}
复制代码

那是由于should查询的相关性得分计算过程是:orm

  1. 使用match查询"elasticsearch aggs"时,首先会被拆分为elasticsearch和aggs两个分词;
  2. 而后使用should里面的每一个子句去查询同一个文档:
  3. 文档1的body和title都命中elasticsearch,知足should中的两个子句,文档得2分;
  4. 文档2的title命中elasticsearch和aggs,可是只知足了should中关于title的子句,文档得1分,
  5. 因此最后文档1的得分高于文档2,尽管文档2的匹配度更高。

那么,如何才能让匹配度更高的文档2的相关性得分高于文档1呢? 那么须要使用dis_max查询了。
dis_max查询的得分计算:
以最佳匹配的子句的得分做为整个文档的相关性得分。索引

POST /book/_search?size=1000
{
  "query": {
    "dis_max": {
      "tie_breaker": 0.3,
      "queries": [
        {"match": {"body": "elasticsearch aggs"}},
        {"match": {"title": "elasticsearch aggs"}}
        ]
    }
  }
}
复制代码

那么,dis_max查询过程当中文档1和文档2的得分计算过程为:ip

  1. 使用match查询"elasticsearch aggs"时,首先会被拆分为elasticsearch和aggs两个分词;
  2. 而后使用should里面的每一个子句去查询同一个文档:
  3. 文档1的body和title都命中elasticsearch,body子句得1分,title子句也是1分,最后取两个子句中的最高分做为文档1的最后得分,即最后文档1的相关性得分为1分;
  4. 文档2的title命中elasticsearch和aggs,body没有命中任何分词,因此title子句得分为2分,body子句得分为0分,最后去body和title子句的最高分做为文档2的最后的得分,即文档2得2分;
  5. 因此最后文档2的得分高于文档1,符合咱们的需求。
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.87546873,
    "hits" : [
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.87546873,
        "_source" : {
          "body" : "single value search",
          "title" : "elasticsearch aggs query"
        }
      },
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.80960923,
        "_source" : {
          "body" : "elasticsearch filter",
          "title" : "elasticsearch basic query"
        }
      }
    ]
  }
}
复制代码
相关文章
相关标签/搜索