大數據利器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"
        }
      }
    ]
  }
}
複製代碼
相關文章
相關標籤/搜索