Cardinality Aggregation(基數聚合)
這是一種單值指標聚合,用於計算不同值(distinct values)的近似計數.
譯者注:類似於SQL中的"SELECT COUNT(DISTINCT ColumnName) FROM TableName;"語句.
其值可以從文檔的特定字段提取,也可通過腳本來生成.
假設您正在為商店銷售情況編制索引,並希望計算出與查詢相匹配的已售出產品的唯一數量:
POST /sales/_search?size=0
{
"aggs" : {
"type_count" : {
"cardinality" : {
"field" : "type"
}
}
}
}
響應:
{
...
"aggregations" : {
"type_count" : {
"value" : 3
}
}
}
精確控制
此聚合還接受precision_threshold 選項:
POST /sales/_search?size=0
{
"aggs" : {
"type_count" : {
"cardinality" : {
"field" : "type",
"precision_threshold": 100 #1
}
}
}
}
1.precision_threshold 選項用於控制內存交換的準確性,並定義一個唯一計數,低於該計數的計數則視為比較準確,高於該值的計數則視為不準確(失真).最大支持40000,高於此值的計數效果與40000相同. 默認值為3000.
計數是近似值
計算精確值需要將值加載進hash集合並返回其大小. 當處理高基數據數據集合或需要較高內存的大值時,由於ES需要與各個節點的分片進行通信,因此它會消耗大量的集群資源(不具備具伸縮性).
基數聚合基於HyperLogLog++算法,通過值的哈希來計算,並具有如下特性:
- 可配置的精度,決定如何交換內存的準確性,
- 低基數的精確度,
- 固定內存消耗:無論是數十億還是更多的唯一值,內存使用量僅取決於配置精度。
對於設為c的precision_threshold,實現需要大約需要c * 8字節內存。
下圖顯示了閾值之前和之後的錯誤變化:
對於上述3個閾值,在低於閾值時,計數一直較為準確(雖然不能完全保證,但理論上應該是這樣)。 另請注意,在閾值低至100時,即使計算數百萬個數據,錯誤率也依然非常低。
預計算哈希值
在具有高基數的字符串字段上,先將字段值的哈希值存儲在索引中,然後再在此字段上運行基數聚合,這樣效果可能會更快。 要實現這一點,可通過客戶端來計算哈希值,或使用mapper-murmur3插件來計算哈希值。
注意
預計算哈希通常僅在非常大或高基數字段上有用,因為它能顯著節省CPU和內存。
但在數字字段上,散列也非常快,並且存儲原始值所需的內存要比存儲哈希少。
對於低基數字符串字段也是如此,尤其是那些能經過優化,能確保每個字段的唯一值最多計算一次哈希值的情況。
Script
基數指標支持腳本,由於需要動態計算哈希值,因此必須注意性能影響.
POST /sales/_search?size=0
{
"aggs" : {
"type_promoted_count" : {
"cardinality" : {
"script": {
"lang": "painless",
"source": "doc['type'].value + ' ' + doc['promoted'].value"
}
}
}
}
}
它會使用painless腳本語言(不帶腳本參數)來將script參數解析為內聯腳本.
要使用存儲腳本,可使用如下語法:
POST /sales/_search?size=0
{
"aggs" : {
"type_promoted_count" : {
"cardinality" : {
"script" : {
"id": "my_script",
"params": {
"type_field": "type",
"promoted_field": "promoted"
}
}
}
}
}
}
Missing value
missing 參數用於定義如何處理文檔中的缺失值.默認,它會忽略缺失值,但也可以將其視為有值字段.
POST /sales/_search?size=0
{
"aggs" : {
"tag_cardinality" : {
"cardinality" : {
"field" : "tag",
"missing": "N/A" #1
}
}
}
}
1.tag字段無值的文檔會與具有N/A值的文檔位於同一桶.
全部指標聚合,請參考
單值指標聚合
多值指標聚合
地理位置相關聚合
可執行Map-Reduce計算的聚合
閱讀更多 Java源 的文章