在前文Elastic Search 聚合笔记中已经介绍了Elastic Search聚合的基本用法,但这些常规的统计有的时候会不够用,Elastic Search提供了不少其它的聚合方式来补充,本文这里就介绍下其中非常灵活实用的bucket script的基本用法。

例如,我们在进行统计分析的时候,除了统计数量外,往往还会要求统计出满足某条件的数量占总数的比例,需要经过如下三个步骤。

  1. 求出当前文档数量
  2. 求出满足条件的文档的数量
  3. 计算两个数量的百分比

前两个数据还比较好说,只需要加一个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" },
    //... ...
  }
}

posted on 2020-03-14 23:39  天方  阅读(4240)  评论(1编辑  收藏  举报