Elasticsearch聚合 之 Terms

以前總結過metric聚合的內容,本篇來講一下bucket聚合的知識。Bucket能夠理解爲一個桶,他會遍歷文檔中的內容,凡是符合要求的就放入按照要求建立的桶中。數組

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

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

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

舉個例子:

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

此時,客戶端向ES發送聚合請求,主節點接收到請求後,會向每一個獨立的分片發送該請求。
分片獨立的計算本身分片上的前5個name,而後返回。當全部的分片結果都返回後,在主節點進行結果的合併,再求出頻率最高的前5個,返回給客戶端。文檔

這樣就會形成必定的偏差,好比最後返回的前5箇中,有一個叫A的,有50個文檔;B有49。 可是因爲每一個分片獨立的保存信息,信息的分佈也是不肯定的。 有可能第一個分片中B的信息有2個,可是沒有排到前5,因此沒有在最後合併的結果中出現。 這就致使B的總數少計算了2,原本可能排到第一位,卻排到了A的後面。 io

size與shard_size

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

  • 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" 
             }
         }
    }
}
相關文章
相關標籤/搜索