为什么80%的码农都做不了架构师?>>>
http://www.cnblogs.com/xing901022/p/4947436.html
ES中的聚合被分为两大类:Metric度量和bucket桶。说的通俗点,metric很像SQL中的avg、max、min
等方法,而bucket就有点类似group by
了。
1. Metric聚合
metric的聚合按照值的返回类型可以分为两种:单值聚合 和 多值聚合。
1.1 单值聚合
1.1.1 Sum 求和
这个聚合返回的是单个值,dsl可以参考如下:
"aggs" : {
"intraday_return" : { "sum" : { "field" : "change" } }
}
intraday_return是聚合的名字,同时也会作为请求返回的id值。另外,聚合中是支持脚本的。
{
...
"aggregations": {
"intraday_return": {
"value": 2.18
}
}
}
1.1.2 Min 求最小值
{
"aggs" : {
"min_price" : { "min" : { "field" : "price" } }
}
}
1.1.3 Max 求最大值
{
"aggs" : {
"max_price" : { "max" : { "field" : "price" } }
}
}
1.1.4 avg 求平均值
{
"aggs" : {
"avg_grade" : { "avg" : { "field" : "grade" } }
}
}
1.1.5 cardinality 求唯一值,即不重复的字段有多少
{
"aggs" : {
"author_count" : {
"cardinality" : {
"field" : "author"
}
}
}
}
1.2 多值聚合
1.2.1 percentiles 求百分比
{
"aggs" : {
"load_time_outlier" : {
"percentile_ranks" : {
"field" : "load_time",
"values" : [15, 30]
}
}
}
}
返回结果:
{
...
"aggregations": {
"load_time_outlier": {
"values" : {
"15": 92,
"30": 100
}
}
}
}
1.2.2 stats 统计
{
"aggs" : {
"grades_stats" : { "stats" : { "field" : "grade" } }
}
}
返回结果:
{
...
"aggregations": {
"grades_stats": {
"count": 6,
"min": 60,
"max": 98,
"avg": 78.5,
"sum": 471
}
}
}
1.2.3 extend stats 扩展统计
{
"aggs" : {
"grades_stats" : { "extended_stats" : { "field" : "grade" } }
}
}
返回结果:
{
...
"aggregations": {
"grade_stats": {
"count": 9,
"min": 72,
"max": 99,
"avg": 86,
"sum": 774,
"sum_of_squares": 67028,
"variance": 51.55555555555556,
"std_deviation": 7.180219742846005,
"std_deviation_bounds": {
"upper": 100.36043948569201,
"lower": 71.63956051430799
}
}
}
}
2. Bucket聚合
Bucket可以理解为一个桶,它会遍历文档中的内容,凡是符合要求的就放入按照要求创建的桶中。
它是按照某个字段中的值来分类:比如性别有男、女,就会创建两个桶,分别存放男女的信息。默认会搜集doc_count的信息,即记录有多少男生,有多少女生,然后返回给客户端,这样就完成了一个terms的统计。
2.1 terms聚合
{
"aggs" : {
"genders" : {
"terms" : { "field" : "gender" }
}
}
}
返回结果:
{
...
"aggregations" : {
"genders" : {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets" : [
{
"key" : "male",
"doc_count" : 10
},
{
"key" : "female",
"doc_count" : 10
},
]
}
}
}
2.1.1 terms聚合分析:
2.1.1.1 数据的不确定性
使用terms聚合,结果可能带有一定的偏差与错误性。
举个例子:
我们想要获取name字段中出现频率最高的前5个。
此时,客户端向ES发送聚合请求,主节点接收到请求后,会向每个独立的分片发送该请求。
分片独立的计算自己分片上的前5个name,然后返回。当所有的分片结果都返回后,在主节点进行结果的合并,再求出频率最高的前5个,返回给客户端。这样就会造成一定的误差,比如最后返回的前5个中,有一个叫A的,有50个文档;B有49。但是由于每个分片独立的保存信息,信息的分布也是不确定的。有可能第一个分片中B的信息有2个,但是没有排到前5,所以没有在最后合并的结果中出现。这就导致B的总数少计算了2,本来可能排到第一位,却排到了A的后面。
2.1.1.2 size与shard_size
为了改善上面的问题,就可以使用size和shard_size参数。
- size参数规定了最后返回的term个数(默认是10个)
- shard_size参数规定了每个分片上返回的个数
- 如果shard_size小于size,那么分片也会按照size指定的个数计算
通过这两个参数,如果我们想要返回前5个,size=5;shard_size可以设置大于5,这样每个分片返回的词条信息就会增多,相应的误差几率也会减小。
2.1.1.3 order排序
order指定了最后返回结果的排序方式,默认是按照doc_count排序。
{
"aggs" : {
"genders" : {
"terms" : {
"field" : "gender",
"order" : { "_count" : "asc" }
}
}
}
}
也可以按照字典方式排序:
{
"aggs" : {
"genders" : {
"terms" : {
"field" : "gender",
"order" : { "_term" : "asc" }
}
}
}
}
可以通过order指定一个单值的metric聚合,来排序。
{
"aggs" : {
"genders" : {
"terms" : {
"field" : "gender",
"order" : { "avg_height" : "desc" }
},
"aggs" : {
"avg_height" : { "avg" : { "field" : "height" } }
}
}
}
}
多值的Metric聚合,要指定使用的多值字段:
{
"aggs" : {
"genders" : {
"terms" : {
"field" : "gender",
"order" : { "height_stats.avg" : "desc" }
},
"aggs" : {
"height_stats" : { "stats" : { "field" : "height" } }
}
}
}
}
2.1.1.4 min_doc_count与shard_min_doc_count
聚合的字段可能存在一些频率很低的词条,如果这些词条数目比例很大,那么就会造成很多不必要的计算。
因此可以通过设置min_doc_count和shard_min_doc_count来规定最小的文档数目,只有满足这个参数要求的个数的词条才会被记录返回。通过名字就可以看出:
- min_doc_count:规定了最终结果的筛选
- shard_min_doc_count:规定了分片中计算返回时的筛选
2.1.1.5 script
桶聚合也支持脚本的使用:
{
"aggs" : {
"genders" : {
"terms" : {
"script" : "doc['gender'].value"
}
}
}
}
以及外部脚本文件:
{
"aggs" : {
"genders" : {
"terms" : {
"script" : {
"file": "my_script",
"params": {
"field": "gender"
}
}
}
}
}
}
2.1.1.6 filter
filter字段提供了过滤的功能,使用两种方式:include可以过滤出包含该值的文档;相反则使用exclude。
{
"aggs" : {
"tags" : {
"terms" : {
"field" : "tags",
"include" : ".*sport.*",
"exclude" : "water_.*"
}
}
}
}
2.1.2 多字段聚合
通常情况,terms聚合都是仅针对于一个字段的聚合。因为该聚合是需要把词条放入一个哈希表中,如果多个字段就会造成n^2的内存消耗。
不过,对于多字段,ES也提供了下面两种方式:
1. 使用脚本合并字段
2. 使用copy_to方法,合并两个字段,创建出一个新的字段,对新字段执行单个字段的聚合。
例如:实现 select SEX,PROF,COUNT(*) from table group by SEX,PROF
{
"size": 0,
"query": {
"match_all": {}
},
"aggs": {
"sexprof": { //使用脚本合并字段并对新字段执行单字段的聚合
"terms": {
"script": {
"inline": "doc['SEX.keyword'].value +'-split-'+ doc['PROF.keyword'].value "
}
}
}
}
}
得到的结果:
{
"aggregations": {
"sexprof": {
"doc_count_error_upper_bound": 5,
"sum_other_doc_count": 379,
"buckets": [
{
"key": "女-split-助教",
"doc_count": 2
},
{
"key": "男-split-讲师",
"doc_count": 1
},
{
"key": "男-split-教授",
"doc_count": 1
}
]
}
}
}
2.1.3 collect模式
对于子聚合的计算,有两种方式:
- depth_first 直接进行子聚合的计算
- breadth_first 先计算出当前聚合的结果,针对这个结果在对子聚合进行计算。
默认情况下ES会使用深度优先,不过可以手动设置成广度优先,比如:
{
"aggs" : {
"actors" : {
"terms" : {
"field" : "actors",
"size" : 10,
"collect_mode" : "breadth_first"
},
"aggs" : {
"costars" : {
"terms" : {
"field" : "actors",
"size" : 5
}
}
}
}
}
}
2.1.4 缺省值Missing value
缺省值指定了缺省的字段的处理方式:
{
"aggs" : {
"tags" : {
"terms" : {
"field" : "tags",
"missing": "N/A"
}
}
}
}
2.2 Histogram 直方图聚合
Elasticsearch支持最直方图聚合,它在数字字段自动创建桶,并会扫描全部文档,把文档放入相应的桶中。这个数字字段既可以是文档中的某个字段,也可以通过脚本创建得出的。
2.2.1 桶的筛选规则
2.2.1.1 min_doc_count过滤
返回document数量大于等于1 的直方图聚合
{
"aggs" : {
"prices" : {
"histogram" : {
"field" : "price",
"interval" : 50,
"min_doc_count" : 1
}
}
}
}
2.2.1.2 extend_bounds,指定最小值和最大值边界
默认情况下,ES中的histogram聚合起始都是自动的,比如price字段,如果没有商品的价钱在0-5之间,0这个桶就不会显示。如果最便宜的商品是11,那么第一个桶就是10.
可以通过设置extend_bounds强制规定最小值和最大值,但是要求必须min_doc_count不能大于0,不然即便是规定了边界,也不会返回。
可以通过设置extend_bounds强制规定最小值和最大值,但是要求必须min_doc_count不能大于0,不然即便是规定了边界,也不会返回。
2.2.1.3 order排序
排序大同小异,可以按照_key,_count,指定排序的聚合进行排序
{
"aggs" : {
"prices" : {
"histogram" : {
"field" : "price",
"interval" : 50,
"order" : { "_key" : "desc" }
}
}
}
}
2.2.1.4 keyed设置返回的方式
正常返回的数据如上面所示,是按照数组的方式返回。如果要按照名字返回,可以设置keyed为true。
之前的返回方式:
设置keyed为true:
{
"aggs" : {
"prices" : {
"histogram" : {
"field" : "price",
"interval" : 50,
"keyed" : true
}
}
}
}
返回的数据为:
{ "aggregations": { "prices": { "buckets": { "0": { "key": 0, "doc_count": 2 }, "50": { "key": 50, "doc_count": 4 }, "150": { "key": 150, "doc_count": 3 } } } } }
2.2.1.5 缺省的值
缺省值通过MissingValue设置:
{
"aggs" : {
"quantity" : {
"histogram" : {
"field" : "quantity",
"interval": 10,
"missing": 0
}
}
}
}
2.3 Date Histogram聚合
Date histogram的用法与histogram差不多,只不过区间上支持了日期的表达式。
{
"aggs":{
"articles_over_time":{
"date_histogram":{
"field":"date",
"interval":"month"
}
}
}
}
interval字段支持多种关键字:`year`, `quarter`, `month`, `week`, `day`, `hour`, `minute`, `second`
也支持对这些关键字进行扩展使用,比如一个半小时可以定义成如下::
{
"aggs":{
"articles_over_time":{
"date_histogram":{
"field":"date",
"interval":"1.5h"
"format":"yyyy-MM-dd" //对返回结果进行格式化
}
}
}
}
2.3.1 time_zone时区的用法
在es中日期支持时区的表示方法,这样就相当于东八区的时间。
{
"aggs":{
"by_day":{
"date_histogram":{
"field":"date",
"interval":"day",
"time_zone":"+08:00"
}
}
}
}
2.3.2 offset 使用偏移值,改变时间区间
默认情况是从凌晨0点到午夜24:00,如果想改变时间区间,可以通过下面的方式,设置偏移值:
{
"aggs":{
"by_day":{
"date_histogram":{
"field":"date",
"interval":"day",
"offset":"+6h"
}
}
}
}
2.3.3 Missing Value缺省字段
当遇到没有值的字段,就会按照缺省字段missing value来计算。
对于其他的一些用法,这里就不过多赘述了,比如脚本、Order、min_doc_count过滤,extended_bounds等都是支持的。
{
"aggs": {
"missing_address": {
"missing": {
"field": "address"
}
}
}
}
结果只返回一个桶
2.4 嵌套聚合
{
"aggs":{
"color_type_max":{
"terms":{
"field": "color"
},
"aggs":{
"max_age": {
"max": {
"field" : "age"
}
}
}
},
"color_type_min":{
"terms":{
"field": "color"
},
"aggs":{
"min_age": {
"min": {
"field" : "age"
}
}
}
}
}
}