在前文Elastic Search 聚合筆記中已經介紹了Elastic Search聚合的基本用法,但這些常規的統計有的時候會不夠用,Elastic Search提供了不少其它的聚合方式來補充,本文這里就介紹下其中非常靈活實用的bucket script的基本用法。
例如,我們在進行統計分析的時候,除了統計數量外,往往還會要求統計出滿足某條件的數量占總數的比例,需要經過如下三個步驟。
-
求出當前文檔數量
-
求出滿足條件的文檔的數量
-
計算兩個數量的百分比
前兩個數據還比較好說,只需要加一個filter bucket即可,例如,我們想求出某bucket下的所有男性數量:
"aggs": {
"男性": {
"filter": { "term": { "性別": "男" } }
}
返回值為
{
"key": "true",
"doc_count": 497,
"男性": { "doc_count": 208 },
"男性比例": { "value": 41.0 }
}
可看到,本身就返回了每個聚合的數量。難點在第3步,需要在前面兩步的基礎上再進行運算,這個就是比較典型的管道聚合了,由於我們當前只是一個簡單的運算,使用bucket script注入一些腳本的功能是很容易實現的,它的基本格式如下:
{
"bucket_script": {
"buckets_path": {
"my_var1": "the_sum",
"my_var2": "the_value_count"
},
"script": "params.my_var1 / params.my_var2"
}
}
主要有兩個參數
-
bucket_path:指定相關上下文變量的查詢路徑,相當於定義變量和變量查詢路徑。其語法規則可參看 bucket_path語法規則,並不復雜,一般情況下也能猜出個大致。
-
script: 腳本內容,支持好幾種語法,默認的類似java,具體可參看官方文檔: Scripting
有了上述基礎后,就可以構建bucket script了,本文示例如下
"aggs": {
"男性": {
"filter": { "term": { "性別": "男" } }
},
"男性比例": {
"bucket_script": {
"buckets_path": {
"p1": "男性._count",
"p2": "_count"
},
"script": "(int)(100 * params.p1 / params.p2)"
}
}
}
這里用了"_count"這個特殊的路徑,它代表文檔的數量,這個在官方文檔中也有介紹:special path。
然后,我們就得到想要的結果了。
{
"key": "true",
"doc_count": 497,
"男性": { "doc_count": 208 },
"男性比例": { "value": 41.0 }
}
本身還是比較簡單的,不過這個有個限制,那就是不能用在頂層聚合中,否則報錯。如果沒有上級聚合,可以用一些規避的方式,例如,構造一個到所有數據的聚合作為頂層聚合。
"aggs": {
"top": {
"terms": { "script": "true" },
//... ...
}
}