Elasticsearch聚合 之 Terms


本篇着重講解的terms聚合,它是按照某個字段中的值來分類:

比如性別有男、女,就會創建兩個桶,分別存放男女的信息。默認會搜集doc_count的信息,即記錄有多少男生,有多少女生,然后返回給客戶端,這樣就完成了一個terms得統計。

Terms聚合

{
    "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聚合,結果可能帶有一定的偏差與錯誤性。

舉個例子:

我們想要獲取name字段中出現頻率最高的前5個。

此時,客戶端向ES發送聚合請求,主節點接收到請求后,會向每個獨立的分片發送該請求。
分片獨立的計算自己分片上的前5個name,然后返回。當所有的分片結果都返回后,在主節點進行結果的合並,再求出頻率最高的前5個,返回給客戶端。

這樣就會造成一定的誤差,比如最后返回的前5個中,有一個叫A的,有50個文檔;B有49。但是由於每個分片獨立的保存信息,信息的分布也是不確定的。有可能第一個分片中B的信息有2個,但是沒有排到前5,所以沒有在最后合並的結果中出現。這就導致B的總數少計算了2,本來可能排到第一位,卻排到了A的后面。

size與shard_size

為了改善上面的問題,就可以使用size和shard_size參數。

  • size參數規定了最后返回的term個數(默認是10個)
  • shard_size參數規定了每個分片上返回的個數
  • 如果shard_size小於size,那么分片也會按照size指定的個數計算

通過這兩個參數,如果我們想要返回前5個,size=5;shard_size可以設置大於5,這樣每個分片返回的詞條信息就會增多,相應的誤差幾率也會減小。

order排序

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

聚合的字段可能存在一些頻率很低的詞條,如果這些詞條數目比例很大,那么就會造成很多不必要的計算。
因此可以通過設置min_doc_count和shard_min_doc_count來規定最小的文檔數目,只有滿足這個參數要求的個數的詞條才會被記錄返回。

通過名字就可以看出:

  • min_doc_count:規定了最終結果的篩選
  • shard_min_doc_count:規定了分片中計算返回時的篩選

script

桶聚合也支持腳本的使用:

{
    "aggs" : { "genders" : { "terms" : { "script" : "doc['gender'].value" } } } }

以及外部腳本文件:

{
    "aggs" : { "genders" : { "terms" : { "script" : { "file": "my_script", "params": { "field": "gender" } } } } } }

filter

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也提供了下面兩種方式:

  • 1 使用腳本合並字段
  • 2 使用copy_to方法,合並兩個字段,創建出一個新的字段,對新字段執行單個字段的聚合。

collect模式

對於子聚合的計算,有兩種方式:

  • depth_first 直接進行子聚合的計算
  • breadth_first 先計算出當前聚合的結果,針對這個結果在對子聚合進行計算。

默認情況下ES會使用深度優先,不過可以手動設置成廣度優先,比如:

{
    "aggs" : { "actors" : { "terms" : { "field" : "actors", "size" : 10, "collect_mode" : "breadth_first" }, "aggs" : { "costars" : { "terms" : { "field" : "actors", "size" : 5 } } } } } }

缺省值Missing value

缺省值指定了缺省的字段的處理方式:

{
    "aggs" : { "tags" : { "terms" : { "field" : "tags", "missing": "N/A" } } } }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM