今朋友问我关于python elasticsearch aggs的问题,虽然我自己也经常使用es,但因为业务的关系,能用到的elasticsearch语句来来回回就那些,然后再来回套用那几个DSL局域就可以了… 趁着这次跟别人交流的机会,我也把elasticsearch aggs聚合计算也好好的看看。
最近文章总是被无情的转走,这里标注下es aggs的原文链接:
和查询DSL一样,聚合(Aggregations)也拥有一种可组合(Composable)的语法:
为了掌握聚合aggs语法,你一定要了解两个主要概念:
Buckets(桶):
满足某个条件的文档集合。
Metrics(指标):
为某个桶中的文档计算得到的统计信息。
就是这样!每个聚合只是简单地由一个或者多个桶,零个或者多个指标组合而成。
桶和SQL中的组(Grouping)拥有相似的概念,而指标则与COUNT(),SUM(),MAX(),MIN(), AVG()等相似。
让我们仔细看看这些概念。
桶(Buckets)
一个桶就是满足特定条件的一个文档集合:
一名员工要么属于男性桶,或者女性桶。
城市杭州属于浙江省这个桶。
日期2014-10-28属于十月份这个桶。
随着聚合被执行,每份文档中的值会被计算来决定它们是否匹配了桶的条件。如果匹配成功,那么该文档会被置入该桶中,同时聚合会继续执行。
桶也能够嵌套在其它桶中,能让你完成层次或者条件划分这些需求。比如, 杭州可以被放置在浙江省这个桶中,而整个浙江省有属于中国这个桶中。
指标(Metrics)
桶能够让我们对文档进行有意义的划分,但是最终我们还是需要对每个桶中的文档进行某种指标计算。分桶是达到最终目的的手段:提供了对文档进行划分的方法,从而让你能够计算需要的指标。
多数指标仅仅是简单的数学运算(比如,min,mean,max以及sum),它们使用文档中的值进行计算。在实际应用中,指标能够让你计算例如平均薪资,最高出售价格,或者百分之95的查询延迟。
一个聚合就是一些桶和指标的组合。一个聚合可以只有一个桶,或者一个指标,或者每样一个。在桶中甚至可以有多个嵌套的桶。比如,我们可以将文档按照其所属国家进行分桶,然后对每个桶计算其平均薪资(一个指标)。
因为桶是可以嵌套的,我们能够实现一个更加复杂的聚合操作:
将文档按照国家进行分桶。(桶)
然后将每个国家的桶再按照性别分桶。(桶)
然后将每个性别的桶按照年龄区间进行分桶。(桶)
最后,为每个年龄区间计算平均薪资。
懂了桶和指标的概念后,我们来试着看下面的几个elasticsearch表达式.
{ "aggs" : { "colors" : { "terms" : { "field" : "color" } } } }
aggs是聚合的顶级标注,colors是名字,算是这次聚合任务的名字。 然后我们定义一个terms类型的桶,字段是color字段。
一句话简单说明,就是 把color进行group by分组。 虽然语法上看起来只是分组而已,但elasticsearch已经帮你把每种颜色都进行了聚合求数目,并且帮你按照数目进行从大到小排序。
{ "aggs": { "colors": { "terms": { "field": "color" }, "aggs": { "avg_price": { "avg": { "field": "price" } } } } } }
我们看到上面的聚合语句的难度要复杂与上次的,因为多了一个avg求平均数的指标。avg本身的意思很好理解,就是给price做avg。但我们需要注意的是,他的取值范围 ! 他是受限于他上层的桶 ,他的上层桶只有一个,那就是terms的那个。 那这个语句所要表达的意思就很明显了。 首先要针对每个颜色进行分组,然后每个颜色的所有的价格,进行求平均值。
{ "aggs": { "colors": { "terms": { "field": "color" }, "aggs": { "avg_price": { "avg": { "field": "price" } }, "make": { "terms": { "field": "make" } } } } } }
这里多了一个跟avg平级的聚合,他其实也是在做桶的操作,但他跟avg一样都是存在于terms color那个桶的。 这个语句要表达的意思是说,不仅显示每个颜色的数目,每个颜色的平均值,每个颜色里面针对make(品牌)进行分组统计。
{ "aggs": { "colors": { "terms": { "field": "color" }, "aggs": { "avg_price": { "avg": { "field": "price" } }, "make" : { "terms" : { "field" : "make" }, "aggs" : { "min_price" : { "min": { "field": "price"} }, "max_price" : { "max": { "field": "price"} } } } } } } }
相比之前的,我们可以看到明显多出min_price max_price这两个字段。 基于上面的解释,我们再继续描述下他所表达的意思。不仅显示每个颜色的数目,每个颜色的平均值,每个颜色里面针对make(品牌)进行分组统计,然后继续得到最便宜的价格,最贵的价格。
{ "aggs": { "sales": { "date_histogram": { "field": "sold", "interval": "month", "format": "yyyy-MM-dd", "min_doc_count" : 0, "extended_bounds" : { "min" : "2014-01-01", "max" : "2014-12-31" } } } } }
date_histogram是aggs表述时间范围的,这也是我们经常会用到的。 上面的聚合语句表达的意思是说,2014整年里按照每个月的维度进行分组聚合,求每个月有多少item。
大家一定要理解Buckets(桶)及Metrics(指标)概念,buckets多层嵌套的概念,想基于哪个桶做统计计算,只需要嵌入一层aggs就可以了。
对于用python操作elasticsearch的朋友,可以看看我用来学习elasticsearch的语法解析模块。 通过这个可以很好的学习es语法。 elasticsearch_parse是改自官方es orm模块。
https://github.com/rfyiamcool/elasticsearch_parse
END… … !