ES 23 - 檢索和過濾的區別 (query vs. filter)

瘦風發表於2019-07-31

本文以 ES 6.6.5 版本為例進行演示.

1 filter與query示例

1.1 準備測試資料

PUT website/_doc/1
{
    "title": "小白學ES01",
    "desc": "the first blog about es",
    "level": 1, 
    "post_date": "2018-10-10",
    "post_address": {
        "country": "China",
        "province": "GuangDong",
        "city": "GuangZhou"
    }
}

PUT website/_doc/2
{
    "title": "小白學ES02",
    "desc": "the second blog about es",
    "level": 3,
    "post_date": "2018-11-11",
    "post_address": {
        "country": "China",
        "province": "ZheJiang",
        "city": "HangZhou"
    }
}

1.2 搜尋測試

搜尋條件: 搜尋部落格等級(level)大於等於2, 同時釋出日期(post_date)是2018-11-11的部落格:

(1) 不使用filter:

GET website/_doc/_search
{
    "query": {
        "bool": {
            "must": [
                { "match": { "post_date": "2018-11-11" } }, 
                { "range": { "level": { "gte": 2 } } }
            ]
        }
    }
}
// 結果資訊: 
"hits": {
    "total": 1,
    "max_score": 2.0,
    "hits": [
        {
            "_index": "website2",
            "_type": "blog",
            "_id": "2",
            "_score": 2.0,          // 評分為2.0
            "_source": {
                "title": "小白學ES02",
                "desc": "the second blog about es",
                "level": 3,
                "post_date": "2018-11-11",
                "post_address": {
                    "country": "China",
                    "province": "ZheJiang",
                    "city": "HangZhou"
                }
            }
        }
    ]
}

(2) 使用filter:

GET website/_doc/_search
{
    "query": {
        "bool": {
            "must": { 
                "match": { "post_date": "2018-11-11" }
            }, 
            "filter": {
                "range": { "level": { "gte": 2 } }
            }
        }
    }
}
// 結果資訊: 
"hits": {
    "total": 1,
    "max_score": 1.0,
    "hits": [
        {
            "_index": "website2",
            "_type": "blog",
            "_id": "2",
            "_score": 1.0,      // 評分為1.0
            "_source": {
                "title": "小白學ES02",
                "desc": "the second blog about es",
                "level": 3,
                "post_date": "2018-11-11",
                "post_address": {
                    "country": "China",
                    "province": "ZheJiang",
                    "city": "HangZhou"
                }
            }
        }
    ]
}

2 filter與query的區別

filter和query一起使用時, 會先執行filter.

2.1 相關度處理上的不同

filter —— 只根據搜尋條件過濾出符合的文件, 將這些文件的評分固定為1, 忽略TF/IDF資訊, 不計算相關度分數;
query —— 先查詢符合搜尋條件的文件, 然後計算每個文件對於搜尋條件的相關度分數, 再根據評分倒序排序.

建議:

  • 如果對搜尋結果有排序的要求, 要將最匹配的文件排在最前面, 就用query;
  • 如果只是根據一定的條件篩選出部分資料, 不關注結果的排序, 就用filter.

2.2 效能上的對比

filter 效能更好, 無排序 —— 不計算相關度分數, 不用根據相關度分數進行排序, 同時ES內部還會快取(cache)比較常用的filter的資料 (使用bitset <0或1> 來記錄包含與否).

query 效能較差, 有排序 —— 要計算相關度分數, 要根據相關度分數進行排序, 並且沒有cache功能.

2.3 對比結論

1) 業務關心的、需要根據匹配的相關度進行排序的搜尋條件 放在 query 中;

2) 業務不關心、不需要根據匹配的相關度進行排序的搜尋條件 放在 filter 中.

版權宣告

作者: 馬瘦風(https://healchow.com)

出處: 部落格園 馬瘦風的部落格(https://www.cnblogs.com/shoufeng)

感謝閱讀, 如果文章有幫助或啟發到你, 點個[好文要頂?] 或 [推薦?] 吧?

本文版權歸博主所有, 歡迎轉載, 但 [必須在文章頁面明顯位置標明原文連結], 否則博主保留追究相關人員法律責任的權利.

相關文章