1. 程式人生 > >Elasticsearch查詢分析

Elasticsearch查詢分析

一,elasticsearch查詢分為query查詢和filter查詢兩種方式。

query查詢過程:
1,比較查詢條件;
2,然後計算分值,最後返回文件結果。
這種查詢方式適合於全文檢索類的查詢。

filter查詢
1,判斷是否滿足查詢條件,如果不滿足,會快取查詢過程(記錄該文件不滿足結果);
2,滿足的話,就直接快取結果。
這種查詢方式適合於精確值匹配方式的查詢。

綜上所述,filter快在兩個方面:
1 對結果進行快取;
2 避免計算文件相關性分值。

二,filter的型別。
但是這裡需要注意的是filter也分為兩種型別的filter:post_filter和filtered

post_filter(先查詢再過濾)

    "query": {
        "match":{"title":"cat"}
    },
    "post_filter":{
        "term":{"year":1999}
    }
}
即上面的查詢過程為:先按照"match":{"title":"cat"} 進行匹配查詢,然後對結果進行過濾。這樣這種filter不會提高效能。

filtered(先過濾再查詢,速度快)
{
    "query": {
        "filtered": {
            "query": {
                "match": {
                    "title": "cat"
                }
            }, 
            "filter": {
                "term": {
                    "year": 1999
                }
            }
        }
    }
}
上面的查詢過程為:
1,先按照
"filter": {
  "term": {
        "year": 1999
    }
}
進行過濾,注意針對這個filter的查詢結果進行快取,同時也不計算文件的相關性分值。


2,再按照
"query": {
    "match": {
        "title": "cat"
    }
}
對第一步中的過濾結果再進行query查詢。


看到上面的這種複雜的方式那麼為什麼不全部使用效率更高的filter查詢呢,例如下面這樣?
{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "title": "cat"
              }
            },
            {
              "term": {
                "year": 1999
              }
            }
          ]
        }
      }
    }
  }
}


這是因為:
1,這樣的話即保證了query查詢的特性;
2,又沒有浪費filter快取,當然如果這個內容沒必要快取的話也就沒畢業使用query了。


api使用,本來沒想寫過java api方面的內容,但是發現es至少在這裡做的還是比較隱晦的,找了好久才找到在哪裡,最開始一度還誤導filter和post filter是一樣的
//FilteredQueryBuilder qbuilder = QueryBuilders.filteredQuery(QueryBuilders.boolQuery(),filterBuilder);
//第一個引數是設定query,第二個引數是設定filter
FilteredQueryBuilder qbuilder = QueryBuilders.filteredQuery(null,filterBuilder);


SearchRequestBuilder request = client.prepareSearch(Config.getString("dong.es.index"))
    .setSearchType(SearchType.COUNT)
    .setTypes(Config.getString("dong.es.type"))
    .setQuery(qbuilder);


注意上面的方式在2.2版本被廢棄呼叫,改用bool的方式
{
    "query": {
        "bool": {
            "must": {
                "match": {
                    "title": "cat"
                }
            }, 
            "filter": {
                "term": {
                    "year": 1999
                }
            }
        }
    }
}


除了上面提到的filtered過濾和post_filter過濾這兩種過濾方式之外,有時候還會看到過另外一種過濾方式filter outside過濾方式,如下面的case2:


Case 1: 

    "query": { 
        "filtered": { 
            "filter": { 
                "prefix": { 
                    "name": "blah" 
                } 
            }, 
            "query": { 
                "term": { 
                    "dept": "engineering" 
                } 
            } 
        } 
    } 



AND, 
Case 2: 

    "query": { 
        "term": { 
            "dept": "engineering" 
        } 
    }, 
    "filter": { 
        "prefix": { 
            "name": "blah" 
        } 
    } 

不過我並沒有用過這種方式,這裡也就不深究了,不過網上簡單查了一下資料為:
1,case2和post_filter的查詢過程基本一樣,也是事後過濾;
2,case這種方式可能應用於facts裡面或者是Aggregations裡   。。。。。。。
3,網上的資料:
http://stackoverflow.com/questions/28958882/elasticsearch-filtered-query-vs-filter
http://elasticsearch-users.115913.n3.nabble.com/Filtered-query-vs-using-filter-outside-td3960119.html

參考資料:
es原始碼
https://segmentfault.com/a/1190000004429689
http://udn.yyuap.com/doc/mastering-elasticsearch/chapter-2/27_README.html