以前總結過metric聚合的內容,本篇來講一下bucket聚合的知識。Bucket能夠理解爲一個桶,他會遍歷文檔中的內容,凡是符合要求的就放入按照要求建立的桶中。數組
好比性別有男、女,就會建立兩個桶,分別存放男女的信息。默認會蒐集doc_count的信息,即記錄有多少男生,有多少女生,而後返回給客戶端,這樣就完成了一個terms得統計。code
{ "aggs" : { "genders" : { "terms" : { "field" : "gender" } } } }
獲得的結果以下:排序
{ ... "aggregations" : { "genders" : { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets" : [ { "key" : "male", "doc_count" : 10 }, { "key" : "female", "doc_count" : 10 }, ] } } }
使用terms聚合,結果可能帶有必定的誤差與錯誤性。ip
咱們想要獲取name字段中出現頻率最高的前5個。內存
此時,客戶端向ES發送聚合請求,主節點接收到請求後,會向每一個獨立的分片發送該請求。
分片獨立的計算本身分片上的前5個name,而後返回。當全部的分片結果都返回後,在主節點進行結果的合併,再求出頻率最高的前5個,返回給客戶端。文檔
這樣就會形成必定的偏差,好比最後返回的前5箇中,有一個叫A的,有50個文檔;B有49。 可是因爲每一個分片獨立的保存信息,信息的分佈也是不肯定的。 有可能第一個分片中B的信息有2個,可是沒有排到前5,因此沒有在最後合併的結果中出現。 這就致使B的總數少計算了2,原本可能排到第一位,卻排到了A的後面。 io
爲了改善上面的問題,就可使用size和shard_size參數。file
經過這兩個參數,若是咱們想要返回前5個,size=5;shard_size能夠設置大於5,這樣每一個分片返回的詞條信息就會增多,相應的偏差概率也會減少。 遍歷
order指定了最後返回結果的排序方式,默認是按照doc_count排序。請求
{ "aggs" : { "genders" : { "terms" : { "field" : "gender", "order" : { "_count" : "asc" } } } } }
也能夠按照字典方式排序:
{ "aggs" : { "genders" : { "terms" : { "field" : "gender", "order" : { "_term" : "asc" } } } } }
固然也能夠經過order指定一個單值的metric聚合,來排序。
{ "aggs" : { "genders" : { "terms" : { "field" : "gender", "order" : { "avg_height" : "desc" } }, "aggs" : { "avg_height" : { "avg" : { "field" : "height" } } } } } }
同時也支持多值的Metric聚合,不過要指定使用的多值字段:
{ "aggs" : { "genders" : { "terms" : { "field" : "gender", "order" : { "height_stats.avg" : "desc" } }, "aggs" : { "height_stats" : { "stats" : { "field" : "height" } } } } } }
聚合的字段可能存在一些頻率很低的詞條,若是這些詞條數目比例很大,那麼就會形成不少沒必要要的計算。
所以能夠經過設置min_doc_count和shard_min_doc_count來規定最小的文檔數目,只有知足這個參數要求的個數的詞條纔會被記錄返回。
桶聚合也支持腳本的使用:
{ "aggs" : { "genders" : { "terms" : { "script" : "doc['gender'].value" } } } }
以及外部腳本文件:
{ "aggs" : { "genders" : { "terms" : { "script" : { "file": "my_script", "params": { "field": "gender" } } } } } }
filter字段提供了過濾的功能,使用兩種方式:include能夠過濾出包含該值的文檔;相反則使用exclude。
例如:
{ "aggs" : { "tags" : { "terms" : { "field" : "tags", "include" : ".*sport.*", "exclude" : "water_.*" } } } }
上面的例子中,最後的結果應該包含sport而且不包含water。
也支持數組的方式,定義包含與排除的信息:
{ "aggs" : { "JapaneseCars" : { "terms" : { "field" : "make", "include" : ["mazda", "honda"] } }, "ActiveCarManufacturers" : { "terms" : { "field" : "make", "exclude" : ["rover", "jensen"] } } } }
一般狀況,terms聚合都是僅針對於一個字段的聚合。由於該聚合是須要把詞條放入一個哈希表中,若是多個字段就會形成n^2的內存消耗。
不過,對於多字段,ES也提供了下面兩種方式:
對於子聚合的計算,有兩種方式:
默認狀況下ES會使用深度優先,不過能夠手動設置成廣度優先,好比:
{ "aggs" : { "actors" : { "terms" : { "field" : "actors", "size" : 10, "collect_mode" : "breadth_first" }, "aggs" : { "costars" : { "terms" : { "field" : "actors", "size" : 5 } } } } } }
缺省值指定了缺省的字段的處理方式:
{ "aggs" : { "tags" : { "terms" : { "field" : "tags", "missing": "N/A" } } } }