在前文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" },
//... ...
}
}