顿搜
08. ES分桶聚合查询——ElasticSerach搜索专栏
06/16
Elasticsearch中的桶在概念上类似于SQL的分组(GROUP BY),而聚合桶中的指标则类似于COUNT()、SUM()、MAX()等统计方法
一、简单的聚合
GET /dbindex/_search
{
"size" : 0, // 表示只要统计后的结果,原始数据不需要返回,如果是大于0的,则会返回对应数量的文档数据。
"aggs" : { // 固定语法,聚合分析都要声明aggs或者aggregations。
"popular_colors" : { // 聚合的名称,可以随便命名,但建议规范命名
"terms" : { // 表示按哪个字段进行分组
"field" : "color.keyword" // 表示具体的字段名称
}
}
}
}返回结果
{
"aggregations" : {
"popular_colors" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "red",
"doc_count" : 3
},
{
"key" : "green",
"doc_count" : 2
},
{
"key" : "blue",
"doc_count" : 1
}
]
}
}
}二、多个聚合
GET /dbindex/_search
{
"size" : 0,
"aggs" : {
"popular_colors" : {
"terms" : {
"field" : "color.keyword"
}
},
"popular_make" : {
"terms" : {
"field" : "make.keyword"
}
}
}
}返回结果
{
"aggregations" : {
"popular_make" : { // 厂商字段聚合统计结果
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "honda",
"doc_count" : 2
},
{
"key" : "toyota",
"doc_count" : 2
},
{
"key" : "bmw",
"doc_count" : 1
},
{
"key" : "ford",
"doc_count" : 1
}
]
},
"popular_colors" : { // 颜色聚合结果
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "red",
"doc_count" : 3
},
{
"key" : "green",
"doc_count" : 2
},
{
"key" : "blue",
"doc_count" : 1
}
]
}
}
}三、动态脚本聚合
Elasticsearch还支持一些基于脚本(生成运行时的字段)的复杂动态聚合
GET /dbindex/_search
{
"runtime_mappings": {
"make_content_length": {
"type": "long",
"script": "emit(doc['make.keyword'].value.length())" // 运行时脚本计算make字段内容的长度
}
},
"size" : 0,
"aggs": {
"make_length": {
"histogram": {
"interval": 1,
"field": "make_content_length" // 根据运行时make字段的内容长度进行聚合统计
}
}
}
}返回结果
{
"aggregations" : {
"make_length" : {
"buckets" : [
{
"key" : 3.0, // 表示厂商名称的长度
"doc_count" : 1 // 厂商名称长度等于3的文档数量
},
{
"key" : 4.0, // 表示厂商名称的长度
"doc_count" : 1
},
{
"key" : 5.0, // 表示厂商名称的长度
"doc_count" : 2
},
{
"key" : 6.0, // 表示厂商名称的长度
"doc_count" : 2
}
]
}
}
}四、过滤聚合
在SQL中,我们经常会先进行筛选,再进行聚合统计。Elasticsearch中也支持先筛选再聚合
举例:聚合计算厂商toyota出售车的平均价格和出售的总数量
GET /dbindex/_search
{
"size": 0,
"aggs": {
"make_by": {
"filter": { "term": { "make": "toyota" } },
"aggs": {
"avg_price": { "avg": { "field": "price" } }
}
}
}
}返回结果
{
"hits" : {
"total" : {
"value" : 6,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"make_by" : {
"doc_count" : 2,
"avg_price" : {
"value" : 15500.0
}
}
}
}五、filter分组聚合
GET /dbindex/_search
{
"size": 0,
"aggs" : {
"messages" : {
"filters" : {
"other_bucket_key": "other_color",
"filters" : {
"reds" : { "match" : { "color" : "red" }},
"greens" : { "match" : { "color" : "green" }}
}
}
}
}
}返回结果
{
"aggregations" : {
"messages" : {
"buckets" : {
"greens" : {
"doc_count" : 2 // 绿色车辆的数量
},
"reds" : {
"doc_count" : 3 // 红色车辆的颜色
},
"other_color" : {
"doc_count" : 1 // 其他车辆的颜色
}
}
}
}
}六、数值范围聚合
Elasticsearch提供了基于多桶值源的聚合方式。通过这种方式可以定义一组范围,每个范围代表一个桶
GET /dbindex/_search
{
"size": 0,
"aggs": {
"price_ranges": {
"range": {
"field": "price",
"ranges": [ // 如下是一组范围条件
{ "to": 10000 },
{ "from": 10000, "to": 20000 },
{ "from": 20000, "to": 30000 },
{ "from": 40000 }
]
}
}
}
}返回结果
{
"aggregations" : {
"price_ranges" : {
"buckets" : [
{
"key" : "*-10000.0", // 0~10000的聚合结果
"to" : 10000.0,
"doc_count" : 0
},
{
"key" : "10000.0-20000.0", // 10000~20000的聚合结果
"from" : 10000.0,
"to" : 20000.0,
"doc_count" : 3
},
{
"key" : "20000.0-30000.0", // 20000~30000的聚合结果
"from" : 20000.0,
"to" : 30000.0,
"doc_count" : 1
},
{
"key" : "40000.0-*", // 40000以上的聚合结果
"from" : 40000.0,
"doc_count" : 1
}
]
}
}
}七、指定范围间隔聚合
指定范围间隔(Histrogram)来进行聚合统计
举例:聚合统计,根据出售价格范围进行分组,每一组之间价格相差40000
GET /dbindex/_search
{
"size" : 0,
"aggs":{
"price":{
"histogram":{
"field": "price",
"interval": 40000
}
}
}
}返回结果
{
"aggregations" : {
"price" : {
"buckets" : [
{
"key" : 0.0, // 0~40000出售价格的聚合
"doc_count" : 5
},
{
"key" : 40000.0, // 40000~80000出售价格的聚合
"doc_count" : 0
},
{
"key" : 80000.0, // 80000以上出售价格的聚合
"doc_count" : 1
}
]
}
}
}如果还想知道每一种价格区间的最高出售价格、最低出售价格和平均出售价格
GET /dbindex/_search
{
"size" : 0,
"aggs":{
"price":{
"histogram":{
"field": "price",
"interval": 40000
} ,
"aggs": {
"stats": {
"extended_stats": {
"field": "price"
}
}
}
}
}
}返回结果
{
"aggregations":{
"price":{
"buckets":[
{
"key":0,
"doc_count":5,
"stats":{
"count":5,
"min":10000,
"max":30000,
"avg":18200,
"sum":91000,
"sum_of_squares":1881000000,
"variance":44960000,
"variance_population":44960000,
"variance_sampling":56200000
}
},
{
"key":80000,
"doc_count":1,
"stats":{
"count":1,
"min":80000,
"max":80000,
"avg":80000,
"sum":80000
}
}
]
}
}
}八、日期范围聚合
GET /dbindex/_search
{
"size": 0,
"aggs": {
"range": {
"date_range": {
"field": "soldtime",
"format": "yyyy-MM-dd",
"ranges": [
{ "from": "2021-06-30" },
{ "to": "2021-07-01" }
]
}
}
}
}返回结果
{
"aggregations" : {
"range" : {
"buckets" : [
{
"key" : "*-2021-07-01",
"to" : 1.6250976E12,
"to_as_string" : "2021-07-01",
"doc_count" : 3
},
{
"key" : "2021-06-30-*",
"from" : 1.6250112E12,
"from_as_string" : "2021-06-30",
"doc_count" : 3
}
]
}
}
}日期范围统计还支持根据"Date Math"表达式进行范围分解统计
举例:计算5个月之前和之后的销售车辆数量
GET /dbindex/_search
{
"size": 0,
"aggs": {
"range": {
"date_range": {
"field": "soldtime",
"format": "yyyy-MM-dd",
"ranges": [
{ "from": "now-5M/M" },
{ "to": "now-5M/M" }
]
}
}
}
}返回结果
{
"aggregations" : {
"range" : {
"buckets" : [
{
"key" : "*-2021-02-01", // 2021-02-01之前的销售数量
"to" : 1.6121376E12,
"to_as_string" : "2021-02-01",
"doc_count" : 2
},
{
"key" : "2021-02-01-*", // 2021-02-01之后的销售数量
"from" : 1.6121376E12,
"from_as_string" : "2021-02-01",
"doc_count" : 4
}
]
}
}
}