ToB企服应用市场:ToB评测及商务社交产业平台
标题:
Elasticsearch 的DSL查询,聚合查询与多维度数据统计
[打印本页]
作者:
瑞星
时间:
2024-8-5 13:45
标题:
Elasticsearch 的DSL查询,聚合查询与多维度数据统计
搜索
即从一个索引下按照特定的字段或关键词搜索出符合用户预期的一个或者一堆cocument,然后根据文档的相关度得分,在返回的结果集里并根据得分对这些文档举行一定的排序。
聚合
根据业务需求,对文档中的某个或某几个字段举行数据的分组并做一些指标数据的统计分析,比如要盘算一批文档中某个业务字段的总数,匀称数,最大最小值等,都属于聚合的范畴。
以上两个概念后是明白下面实行的基础,如果是传统关系数据库mysql、oracle等存储的数据,也可以搜索和聚合,但是在数据聚合分析一块,毕竟不是它们的强项,而且需要在程序中做大量的处理,耗时费力,尤其是大数据量的环境下就有些力有未逮了。
但在es中,由于内置了聚合统计的相关功能,只需要使用好它的语法即可达到几近及时的聚合统计,和搜索花费时间根本上没有太大差异,因此使用es很适合在数据量大的业务场景下做聚合统计与分析。
高阶概念
Buckets(桶/聚集):满足特定条件的文档的聚集
Metrics(指标):对桶内的文档举行统计盘算(比方最小值,求和,最大值等)
在聚合统计分析中,使用很频仍的一个名词叫
aggs
,它是聚合的关键词之一,下面就用实行来演示一下使用aggs举行数据聚合的多种场景。
1、实行准备数据,首先往es整合批量插入一些实行数据,这里我们以一个家电卖场的电视为背景举行模拟
设定文档中field的相关分词属性。
PUT http://192.168.56.235:9201/demo2
{
"setting":{
"index":{
"number_of_shards":5,
"number_of_replicats":1
}
},
"mappings":{
"sales":{
"properties":{
"price":{
"type":"long"
},
"color":{
"type":"keyword"
},
"brand":{
"type":"keyword"
},
"sold_date":{
"type":"date"
}
}
}
}
}
复制代码
2、批量插入数据
POST http://192.168.56.235:9201/demo2/sales
{ "price" : 1000, "color" : "红色", "brand" : "长虹", "sold_date" : "2016-10-28" }
{ "price" : 2000, "color" : "红色", "brand" : "长虹", "sold_date" : "2016-11-05" }
{ "price" : 3000, "color" : "绿色", "brand" : "小米", "sold_date" : "2017-05-18" }
{ "price" : 1500, "color" : "蓝色", "brand" : "TCL", "sold_date" : "2017-07-02" }
{ "price" : 1200, "color" : "绿色", "brand" : "TCL", "sold_date" : "2018-08-19" }
{ "price" : 2000, "color" : "红色", "brand" : "长虹", "sold_date" : "2017-11-05" }
{ "price" : 8000, "color" : "红色", "brand" : "三星", "sold_date" : "2017-01-01" }
{ "price" : 2500, "color" : "蓝色", "brand" : "小米", "sold_date" : "2018-02-12" }
复制代码
数据准备完毕
2、按照颜色分组统计各种颜色电视的数量
查询语法如下:
GET http://192.168.56.235:9201/demo2/sales/_search
{
"size":0,
"aggs":{
"group_color":{
"terms":{
"field":"color"
}
}
}
}
复制代码
查询结果如下,这里简朴对此中的几个参数和结果名称做一下阐明。
在查询语句中:
size:0表示聚合查询的结果不需要返回中央的文档内容,
group_color 我们自定义的分组名字,最好是见名知意的
在返回结果中:
hits:{},这部分存放的是返回结果的根本统计结果,如果上面的size制指定了不为0,文档内容则会放在这个里面
buckets:存放聚合后的统计结果详细信息,以key-value的形式显现
3、按照颜色分组统计各种颜色电视的数量,并在此基础上,统计出各种颜色电视的匀称代价
分析:
按照color去分bucket,可以拿到每个color bucket中的数量,这个仅仅只是一个bucket操作, doc_count其实只是es的bucket操作默认实行的一个内置metric。
在一个aggs实行的bucket操作(terms),平级的json布局下,再加一个aggs,这个第二个aggs内部,同样取个名字,实行一个metric操作,avg,对之前的每个bucket中的数据的指定的field、price
field,求一个匀称值
就是一个metric,就是一个对一个bucket分组操作之后,对每个bucket都要实行的一个metric,也可以明白乐成嵌套聚合,在es中获取到某个指标的数据后,继续对这个指标的数据举行其他聚合分析也被叫做下钻
该需求查询语句如下:
{
"size":0,
"aggs":{
"group_color":{
"terms":{
"field":"color"
},
"aggs":{
"avg_color_price":{
"avg":{
"field":"price"
}
}
}
}
}
}
复制代码
返回结果如下,通过结果可以很清晰的看出来,在颜色统计分析的基础上,每一个{}里面还增长了一个指标,即自定义的盘算匀称值的avg_color_price,这个查询几乎是毫秒级的,根本没有延迟,如果转化为sql查询应该是这样的:
select avg(price) from tvs.sales group by color
复制代码
4、根据颜色分组,求出每种颜色的电视代价的最大值,最小值,匀称值
{
"size":0,
"aggs":{
"group_by_color":{
"terms":{
"field":"color"
},
"aggs":{
"max_price":{
"max":{
"field":"price"
}
},
"min_price":{
"min":{
"field":"price"
}
},
"avg_price":{
"avg":{
"field":"price"
}
}
}
}
}
}
复制代码
所得结果如下:
{
"took": 4,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 7,
"max_score": 0,
"hits": []
},
"aggregations": {
"group_by_color": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "红色",
"doc_count": 4,
"max_price": {
"value": 8000
},
"min_price": {
"value": 1000
},
"avg_price": {
"value": 3250
}
},
{
"key": "蓝色",
"doc_count": 2,
"max_price": {
"value": 2500
},
"min_price": {
"value": 1500
},
"avg_price": {
"value": 2000
}
},
{
"key": "绿色",
"doc_count": 1,
"max_price": {
"value": 1200
},
"min_price": {
"value": 1200
},
"avg_price": {
"value": 1200
}
}
]
}
}
}
复制代码
5、按照差异的代价区间对电视举行分别,并求出每个代价区间的电视的匀称代价
在es中根据区间间隔分别,有一个叫做 histogram的语法可以帮助我们实行,雷同于terms,也是举行bucket分组操作,吸收一个field,按照这个field的值的各个范围区间,举行bucket分组操作。
“histogram”:{
“field”: “price”,
“interval”: 2000
},
复制代码
interval:2000,分别范围,0 ~ 2000,2000 ~ 4000,4000 ~ 6000,6000 ~ 8000,8000 ~ 10000,buckets
根据price的值,比如2500,看落在哪个区间内,比如2000 ~ 4000,此时就会将这条数据放入2000 ~ 4000对应的谁人bucket中
bucket分别的方法terms,将field值相同的数据分别到一个bucket中
bucket有了之后,一样的,去对每个bucket实行avg,count,sum,max,min,等各种
metric
操作,聚合分析
{
"size":0,
"aggs":{
"interval_price":{
"histogram":{
"field":"price",
"interval":2000
},
"aggs":{
"revenue":{
"avg":{
"field":"price"
}
}
}
}
}
}
复制代码
查询的结果如下:可以看到,按照2000一个等级将全部电视的代价分别在差异的区间了,并将每个区间的代价匀称值统计了出来
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 7,
"max_score": 0,
"hits": []
},
"aggregations": {
"interval_price": {
"buckets": [
{
"key": 0,
"doc_count": 3,
"revenue": {
"value": 1233.3333333333333
}
},
{
"key": 2000,
"doc_count": 3,
"revenue": {
"value": 2166.6666666666665
}
},
{
"key": 4000,
"doc_count": 0,
"revenue": {
"value": null
}
},
{
"key": 6000,
"doc_count": 0,
"revenue": {
"value": null
}
},
{
"key": 8000,
"doc_count": 1,
"revenue": {
"value": 8000
}
}
]
}
}
}
复制代码
6、按照差异的时间区间对电视举行分别,并求出每个代价区间的电视的匀称代价
date histogram
,按照我们指定的某个date类型的日期field,以及日期interval,按照一定的日期间隔,去分别bucket,这个概念的明白和上一个有点雷同,可以对照明白。
date interval = 1 month
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
:纵然某个日期interval,2017-01-01~2017-01-31中,一条数据都没有,那么这个区间也是要返回的,不然默认是会过滤掉这个区间的
extended_bounds,min,max
:分别bucket的时候,会限定在这个起始日期,和截止日期内
根据上述分析我们构建查询语句
{
"size":0,
"aggs":{
"sales":{
"date_histogram":{
"field":"sold_date",
"interval":"month",
"format":"yyyy-MM-dd",
"min_doc_count":0,
"extended_bounds":{
"min":"2017-01-01",
"max":"2018-12-31"
}
}
}
}
}
复制代码
返回结果如下,按照月份,将指定区间内
各个月份
的数量做了统计
当然,如果我们以为按照月份统计粒度太细,也可以根据
季度
对数据举行统计,只需要将
month
换成
quarter
即可,查询语法如下:
{
"size":0,
"aggs":{
"sales":{
"date_histogram":{
"field":"sold_date",
"interval":"quarter",
"format":"yyyy-MM-dd",
"min_doc_count":0,
"extended_bounds":{
"min":"2017-01-01",
"max":"2018-12-31"
}
}
}
}
}
复制代码
查询结果如下:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4