Elasticsearch 之(6)kibana嵌套聚合,下钻分析,聚合分析
两个核心概念:bucket和metric
city name
北京 小李
北京 小王
上海 小张
上海 小丽
上海 小陈
基于city划分buckets
划分出来两个bucket,一个是北京bucket,一个是上海bucket
北京bucket:包含了2个人,小李,小王
上海bucket:包含了3个人,小张,小丽,小陈
按照某个字段进行bucket划分,那个字段的值相同的那些数据,就会被划分到一个bucket中
有一些mysql的sql知识的话,聚合,首先第一步就是分组,对每个组内的数据进行聚合分析,分组,就是我们的bucket
metric:对一个数据分组执行的统计
当我们有了一堆bucket之后,就可以对每个bucket中的数据进行聚合分词了,比如说计算一个bucket内所有数据的数量,或者计算一个bucket内所有数据的平均值,最大值,最小值
北京 小李
北京 小王
上海 小张
上海 小丽
上海 小陈
基于city划分buckets
划分出来两个bucket,一个是北京bucket,一个是上海bucket
北京bucket:包含了2个人,小李,小王
上海bucket:包含了3个人,小张,小丽,小陈
按照某个字段进行bucket划分,那个字段的值相同的那些数据,就会被划分到一个bucket中
有一些mysql的sql知识的话,聚合,首先第一步就是分组,对每个组内的数据进行聚合分析,分组,就是我们的bucket
metric:对一个数据分组执行的统计
当我们有了一堆bucket之后,就可以对每个bucket中的数据进行聚合分词了,比如说计算一个bucket内所有数据的数量,或者计算一个bucket内所有数据的平均值,最大值,最小值
bucket:group by user_id --> 那些user_id相同的数据,就会被划分到一个bucket中
metric,就是对一个bucket执行的某种聚合分析的操作,比如说求平均值,求最大值,求最小值
计算一个数量计算每个tag下的商品数量
GET /ecommerce/product/_search { "size" : 0, "aggs": { "group_by_tags": { "terms": { "field": "tags" } } } }
size:只获取聚合结果,而不要执行聚合的原始数据
aggs:固定语法,要对一份数据执行分组聚合操作
gourp_by_tags:就是对每个aggs,都要起一个名字,这个名字是随机的,你随便取什么都ok
terms:根据字段的值进行分组
field:根据指定的字段的值进行分组将文本
aggs:固定语法,要对一份数据执行分组聚合操作
gourp_by_tags:就是对每个aggs,都要起一个名字,这个名字是随机的,你随便取什么都ok
terms:根据字段的值进行分组
field:根据指定的字段的值进行分组将文本
field的fielddata属性设置为true (正排索引 用于嵌套聚合查询, 后面会详细描述)
PUT /ecommerce/_mapping/product { "properties": { "tags": { "type": "text", "fielddata": true } } }
GET /ecommerce/product/_search { "size": 0, "aggs": { "all_tags": { "terms": { "field": "tags" } } } } { "took": 20, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 4, "max_score": 0, "hits": [] }, "aggregations": { "group_by_tags": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "fangzhu", "doc_count": 2 }, { "key": "meibai", "doc_count": 2 }, { "key": "qingxin", "doc_count": 1 } ] } } }
hits.hits:我们指定了size是0,所以hits.hits就是空的,否则会把执行聚合的那些原始数据给你返回回来
aggregations:聚合结果
gourp_by_tags:我们指定的某个聚合的名称
buckets:根据我们指定的field划分出的buckets
key:每个bucket对应的那个值
doc_count:这个bucket分组内,有多少个数据
每种tag对应的bucket中的数据的
默认的排序规则:按照doc_count降序排序
aggregations:聚合结果
gourp_by_tags:我们指定的某个聚合的名称
buckets:根据我们指定的field划分出的buckets
key:每个bucket对应的那个值
doc_count:这个bucket分组内,有多少个数据
每种tag对应的bucket中的数据的
默认的排序规则:按照doc_count降序排序
对名称中包含yagao的商品,计算每个tag下的商品数量
GET /ecommerce/product/_search { "size": 0, "query": { "match": { "name": "yagao" } }, "aggs": { "all_tags": { "terms": { "field": "tags" } } } }
{ "took": 35, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 3, "max_score": 0, "hits": [] }, "aggregations": { "all_tags": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "fangzhu", "doc_count": 2 }, { "key": "meibai", "doc_count": 1 }, { "key": "qingxin", "doc_count": 1 } ] } } }
source 返回指定field
GET /ecommerce/product/_search { "size": 0, "aggs" : { "group_by_tags" : { "terms" : { "field" : "tags" }, "aggs" : { "top_tags": { "top_hits": { "_source": { "include": "name" }, "size": 1 } } } } } }
计算每个tag下的商品的平均价格/最小价格/最大价格/总价
count:bucket,terms,自动就会有一个doc_count,就相当于是count
avg:avg aggs,求平均值
max:求一个bucket内,指定field值最大的那个数据
min:求一个bucket内,指定field值最小的那个数据
sum:求一个bucket内,指定field值的总和先分组,再算每组的平均值
avg:avg aggs,求平均值
max:求一个bucket内,指定field值最大的那个数据
min:求一个bucket内,指定field值最小的那个数据
sum:求一个bucket内,指定field值的总和先分组,再算每组的平均值
GET /ecommerce/product/_search { "size": 0, "aggs" : { "group_by_tags" : { "terms" : { "field" : "tags" }, "aggs" : { "avg_price": { "avg": { "field": "price" } }, "min_price" : { "min": { "field": "price"} }, "max_price" : { "max": { "field": "price"} }, "sum_price" : { "sum": { "field": "price" } } } } }
avg_price:我们自己取的metric aggs的名字
value:我们的metric计算的结果,每个bucket中的数据的price字段求平均值后的结果
value:我们的metric计算的结果,每个bucket中的数据的price字段求平均值后的结果
{ "took": 3, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 3, "max_score": 0, "hits": [] }, "aggregations": { "group_by_tags": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "fangzhu", "doc_count": 2, "max_price": { "value": 30 }, "min_price": { "value": 25 }, "avg_price": { "value": 27.5 }, "sum_price": { "value": 55 } }, { "key": "meibai", "doc_count": 1, "max_price": { "value": 30 }, "min_price": { "value": 30 }, "avg_price": { "value": 30 }, "sum_price": { "value": 30 } }, { "key": "qingxin", "doc_count": 1, "max_price": { "value": 40 }, "min_price": { "value": 40 }, "avg_price": { "value": 40 }, "sum_price": { "value": 40 } } ] } } }
collect_mode
对于子聚合的计算,有两种方式:
- depth_first 直接进行子聚合的计算
- breadth_first 先计算出当前聚合的结果,针对这个结果在对子聚合进行计算。
计算每个tag下的商品的平均价格,并且按照平均价格降序排序
GET /ecommerce/product/_search { "size": 0, "aggs" : { "all_tags" : { "terms" : { "field" : "tags", "collect_mode" : "breadth_first", "order": { "avg_price": "desc" } }, "aggs" : { "avg_price" : { "avg" : { "field" : "price" } } } } } }
{ "took": 2, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 3, "max_score": 0, "hits": [] }, "aggregations": { "all_tags": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "qingxin", "doc_count": 1, "avg_price": { "value": 40 } }, { "key": "meibai", "doc_count": 1, "avg_price": { "value": 30 } }, { "key": "fangzhu", "doc_count": 2, "avg_price": { "value": 27.5 } } ] } } }
按照指定的价格范围区间进行分组,然后在每组内再按照tag进行分组,最后再计算每组的平均价格
GET /ecommerce/product/_search { "size": 0, "aggs": { "group_by_price": { "range": { "field": "price", "ranges": [ { "from": 0, "to": 20 }, { "from": 20, "to": 40 }, { "from": 40, "to": 50 } ] }, "aggs": { "group_by_tags": { "terms": { "field": "tags" }, "aggs": { "average_price": { "avg": { "field": "price" } } } } } } } }
histogram
类似于terms,也是进行bucket分组操作,接收一个field,按照这个field的值的各个范围区间,进行bucket分组操作
interval:10,划分范围,0~10,10~20,20~30
GET /ecommerce/product/_search { "size" : 0, "aggs":{ "price":{ "histogram":{ "field": "price", "interval": 10 }, "aggs":{ "revenue": { "sum": { "field" : "price" } } } } } }
{ "took": 1, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 3, "max_score": 0, "hits": [] }, "aggregations": { "price": { "buckets": [ { "key": 20, "doc_count": 1, "revenue": { "value": 25 } }, { "key": 30, "doc_count": 1, "revenue": { "value": 30 } }, { "key": 40, "doc_count": 1, "revenue": { "value": 40 } } ] } } }
date histogram
按照我们指定的某个date类型的日期field,以及日期interval,按照一定的日期间隔,去划分bucket
date interval = 1m,
2017-01-01~2017-01-31,就是一个bucket
2017-02-01~2017-02-28,就是一个bucket
然后会去扫描每个数据的date field,判断date落在哪个bucket中,就将其放入那个bucket
min_doc_count:即使某个日期interval,2017-01-01~2017-01-31中,一条数据都没有,那么这个区间也是要返回的,不然默认是会过滤掉这个区间的
extended_bounds,min,max:划分bucket的时候,会限定在这个起始日期,和截止日期内
GET /tvs/sales/_search { "size" : 0, "aggs": { "sales": { "date_histogram": { "field": "sold_date", "interval": "month", "format": "yyyy-MM-dd", "min_doc_count" : 0, "extended_bounds" : { "min" : "2016-01-01", "max" : "2017-12-31" } } } } }
{ "took": 11, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 8, "max_score": 0, "hits": [] }, "aggregations": { "sales": { "buckets": [ { "key_as_string": "2016-01-01", "key": 1451606400000, "doc_count": 0 }, { "key_as_string": "2016-02-01", "key": 1454284800000, "doc_count": 0 }, { "key_as_string": "2016-03-01", "key": 1456790400000, "doc_count": 0 }, { "key_as_string": "2016-04-01", "key": 1459468800000, "doc_count": 0 }, { "key_as_string": "2016-05-01", "key": 1462060800000, "doc_count": 1 }, ..... ] } } }aggregation,scope,一个聚合操作,必须在query的搜索结果范围内执行
出来两个结果,一个结果,是基于query搜索结果来聚合的; 一个结果,是对所有数据执行聚合的
global
就是global bucket,就是将所有数据纳入聚合的scope,而不管之前的query
GET /tvs/sales/_search { "size": 0, "query": { "term": { "brand": { "value": "长虹" } } }, "aggs": { "single_brand_avg_price": { "avg": { "field": "price" } }, "all": { "global": {}, "aggs": { "all_brand_avg_price": { "avg": { "field": "price" } } } } } }
{ "took": 4, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 3, "max_score": 0, "hits": [] }, "aggregations": { "all": { "doc_count": 8, "all_brand_avg_price": { "value": 2650 } }, "single_brand_avg_price": { "value": 1666.6666666666667 } } }single_brand_avg_price:就是针对query搜索结果,执行的,拿到的,就是长虹品牌的平均价格
all.all_brand_avg_price:拿到所有品牌的平均价格