聊聊python elasticsearch聚合计算的用法

今朋友问我关于python elasticsearch aggs的问题,虽然我自己也经常使用es,但因为业务的关系,能用到的elasticsearch语句来来回回就那些,然后再来回套用那几个DSL局域就可以了…  趁着这次跟别人交流的机会,我也把elasticsearch aggs聚合计算也好好的看看。


最近文章总是无情的转走,这里标注下es aggs的原文链接:

http://xiaorui.cc/2015/11/01/%E8%81%8A%E8%81%8Apython-elasticsearch%E8%81%9A%E5%90%88%E8%AE%A1%E7%AE%97%E7%9A%84%E7%94%A8%E6%B3%95/



和查询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… … !


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

发表评论

邮箱地址不会被公开。 必填项已用*标注