- 初始化数据
city name 北京 小李 北京 小王 上海 小张 上海 小丽 上海 小陈
-
按照某个字段进行bucket划分,那个字段的值相同的那些数据,就会被划分到一个bucket中、比如基于city划分buckets,划分出来两个bucket,一个是北京bucket,一个是上海bucket(类似于sql的group by city)
1) 北京bucket:包含了2个人,小李,小王
2)上海bucket:包含了3个人,小张,小丽,小陈 -
类比sql:select max(score) from student group by sex的分组聚合,首先第一步就是分组,第二步是对每个组内的数据进行聚合分析。分组对应的就是bucket;聚合对应的就是metric
metric:对一个数据分组执行的统计
当我们有了一堆bucket之后,就可以对每个bucket中的数据进行聚合分词了,比如说计算一个bucket内所有数据的数量,或者计算一个bucket内所有数据的平均值,最大值,最小值
PUT /tvs { "mappings": { "properties": { "price": { "type": "long" }, "color": { "type": "keyword" }, "brand": { "type": "keyword" }, "sold_date": { "type": "date" } } } } POST /tvs/_bulk { "index": {}} { "price" : 1000, "color" : "红色", "brand" : "长虹", "sold_date" : "2016-10-28" } { "index": {}} { "price" : 2000, "color" : "红色", "brand" : "长虹", "sold_date" : "2016-11-05" } { "index": {}} { "price" : 3000, "color" : "绿色", "brand" : "小米", "sold_date" : "2016-05-18" } { "index": {}} { "price" : 1500, "color" : "蓝色", "brand" : "TCL", "sold_date" : "2016-07-02" } { "index": {}} { "price" : 1200, "color" : "绿色", "brand" : "TCL", "sold_date" : "2016-08-19" } { "index": {}} { "price" : 2000, "color" : "红色", "brand" : "长虹", "sold_date" : "2016-11-05" } { "index": {}} { "price" : 8000, "color" : "红色", "brand" : "三星", "sold_date" : "2017-01-01" } { "index": {}} { "price" : 2500, "color" : "蓝色", "brand" : "小米", "sold_date" : "2017-02-12" }统计哪种颜色电视销量最高
# 等价于select color,count(*) from tbl group by color GET /tvs/_search { "size": 0, "aggs": { "什么颜色的电视销量最高": { "terms": { "field": "color" } } } }
- size:只获取聚合结果,而不要执行聚合的原始数据
- aggs:固定语法,要对一份数据执行分组聚合 *** 作
- 什么颜色的电视销量最高:就是对每个aggs *** 作都要起一个名字,这个名字是随意的,取什么都ok
- terms:根据字段的值进行分组
- field:根据指定的字段的值进行分组
疑问:可不可以一次性对多个字段进行group by
统计每种颜色电视平均价格GET /tvs/_search { "size": 0, "aggs": { "每种的颜色电视": { "terms": { "field": "color" }, "aggs": { "平均价格": { "avg": { "field": "price" } } } } } }
- 按照color去分bucket,默认分完bucket后还会统计每个bucket中的文档个数,因为这是bucket *** 作默认执行的一个内置metric——doc_count。
- 如果要自定义metric聚合 *** 作,在一个aggs执行的bucket *** 作(terms)平级的json结构下再加一个aggs,这个第二个aggs内部,同样取个名字,执行一个metric *** 作,avg,对之前的每个bucket中的数据的指定的field,price field,求一个平均值
疑问:可不可以对不同的bucket执行不同的metric?
bucket嵌套实现颜色+品牌的多层下钻,分析平均价格什么是下钻?
下钻:基于当前的数据,在继续进行分组聚合 *** 作。比如说颜色的分组,然后还要继续对这个分组内的数据再分组,比如一个颜色内,还可以分成多个不同的品牌的组,最后对每个最小粒度的分组执行聚合分析 *** 作,这就叫做下钻分析。
实现从颜色到品牌进行下钻分析:每种颜色的平均价格,以及找到每种颜色每个品牌的平均价格。
比如说,现在红色的电视有4台,同时这4台电视中,有3台是属于长虹的,1台是属于小米的
红色电视中的3台长虹的平均价格是多少?
红色电视中的1台小米的平均价格是多少?
es下钻分析,就要对bucket进行多层嵌套,多次分组
按照多个维度(颜色+品牌)多层下钻分析,而且学会了每个下钻维度(颜色,颜色+品牌),都可以对每个维度分别执行一次metric聚合 *** 作
GET /tvs/_search { "size": 0, "aggs": { "颜色": { "terms": { "field": "color" }, "aggs": { "平均价格": { "avg": { "field": "price" } }, "品牌": { "terms": { "field": "brand" }, "aggs": { "平均价格": { "avg": { "field": "price" } } } } } }, "最高价格": { "max": { "field": "price" } } } }
总结:aggs里面只有分组条件和聚合条件,并且一个aggs里最多只能有一个分组条件;但是可以有任意个聚合条件。我们可以用aggs+分组条件嵌套aggs+分组条件,不断嵌套下去往下分组以实现下钻的功能。
统计每种颜色电视最大最小,总和价格GET /tvs/_search { "size": 0, "aggs": { "颜色": { "terms": { "field": "color" }, "aggs": { "最高价格": { "max": { "field": "price" } }, "最低价格": { "min": { "field": "price" } }, "总和价格": { "sum": { "field": "price" } } } } }histogram按价格区间统计电视销量和销售额
GET /tvs/_search { "size": 0, "aggs": { "价格区间": { "histogram": { "field": "price", "interval": 2000 }, "aggs": { "销售额": { "sum": { "field": "price" } } } } } }date hitogram之统计每月电视销量
GET /tvs/_search { "size": 0, "aggs": { "电视销量": { "date_histogram": { "field": "sold_date", "interval": "month", "extended_bounds": { "min": "2016-01-01" }, "min_doc_count": 1, "format": "yyyy-MM-dd" }, "aggs": { "销售额": { "sum": { "field": "price" } } } } } }
- 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。2017-01-05,就将其放入2017-01-01~2017-01-31,就是一个bucket - min_doc_count:默认为0,表示当桶中文档的数量最少也要等于min_doc_count才会显示出来,否则会过滤掉。比如,2017-01-01~2017-01-31中,一条数据都没有,如果想过滤它则写min_doc_count:1
- extended_bounds,min,max:划分bucket的时候,会限定在这个起始日期,和截止日期内
GET /tvs/_search { "size": 0, "aggs": { "季度": { "date_histogram": { "field": "sold_date", "interval": "quarter", "min_doc_count": 0, "format": "yyyy-MM" }, "aggs": { "品牌": { "terms": { "field": "brand" }, "aggs": { "销售额": { "sum": { "field": "price" } } } } } } } }统计小米有什么颜色的手机
GET /tvs/_search { "size": 0, "query": { "term": { "brand": { "value": "小米" } } }, "aggs": { "颜色": { "terms": { "field": "color" } } } }
aggs是基于query过滤后的范围进行分组的
小米的平均价格 对比所有手机的平均价格GET /tvs/_search { "size": 0, "query": { "term": { "brand": { "value": "小米" } } }, "aggs": { "小米手机": { "avg": { "field": "price" } }, "所有手机": { "global": {}, "aggs": { "平均价格": { "avg": { "field": "price" } } } } } }
- global,让聚合的范围忽略query,就是将所有数据纳入聚合的scope,而不管之前的query。
GET /tvs/_search { "size": 0, "query": { "constant_score": { "filter": { "range": { "price": { "gte": 1200 } } } } }, "aggs": { "平均价格": { "avg": { "field": "price" } } } }
- constant_score:表示该条件的得分是静态的,不用动态计算得分。
- constant_score.filter:filter之所以被constant_score包裹,是因为被过滤的数据是不关心得分的。
TODO
排序:按每种颜色的平均销售额降序排序TODO
去重cardinality:根据销售数据获取共有多少种品牌# 类似于 select count(*) from tvs group by brand GET /tvs/_search { "size": 0, "aggs": { "所有的品牌": { "cardinality": { "field": "brand" } } } } # 校验 GET /tvs/_search { "aggs": { "所有的品牌": { "terms": { "field": "brand" } } } }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)