## 聚合查詢
數據聚合即數據的統計分析。常見的聚合方式如下
* 桶聚合:對數據進行分組,相當于sql的group by
* 指標聚合:對數據集使用max() 、min()、avg()、sum()之類的聚合函數,統計最大值、最小值、平均值、總量等指標
主要概念
* 桶(bucket):滿足特定條件的文檔集合,實質是基于條件來劃分文檔
* 指標(metric):數據集的一些特征值,比如最大值、最小值、平均值
> 支持嵌套,桶聚合可以嵌套桶聚合、指標聚合,指標聚合也可以嵌套桶聚合、指標聚合。
> 對于嵌套的聚合,es只需遍歷一次數據,不用多次循環遍歷數據,速度快、性能高,但聚合、排序都很耗內存。
> 聚合可以對index中的所有文檔使用,也可以對查詢結果使用。
> 只能對keyword字段使用聚合,不能對text字段使用聚合,如果對text使用聚合,會報錯
<br>
## 桶聚合
```
#對全樣數據進行聚合,eg. 統計每個球隊的球員(人數)
GET /nba/_search
{
"aggs": {
"team_buckets": { #自定義的聚合名稱
"terms": { #按關鍵字劃分。不能換成term、match
"field": "team_name", #指定要聚合的字段。按隊名劃分桶,一個隊一個桶,桶內是該隊所有球員的文檔,字段的值即桶名
# "include": ["湖人隊","公牛隊","勇士隊"], #指定參與聚合的值,只聚合這些值
# "exclude": ["湖人隊"], #指定不參與聚合的值,除了這些值其它都參與聚合
"size": 10, #返回的桶數,默認返回所有的桶
# "order": { #桶的排序方式
# "_count": "desc" #按桶中的文檔數降序排列,默認也是按桶中的文檔數降序排列
# }
}
}
},
"size": 0 #返回的文檔數,默認返回每個桶中的所有文檔,設置為0即不返回文檔,可提高查詢速度。如果不需要獲取具體文檔,可設置為0
}
#include、exclude可以使用通配符,點號表示任意一個字符,*表示任意多個字符
#按范圍劃分桶之自定義區間,eg.統計指定年齡區間上的用戶數量
GET /user/_search
{
"aggs": {
"age_range": { #自定義的聚合名稱
"range": { #按范圍劃分
"field": "age", #指定字段
"ranges": [ #劃分區間
{
"to": 12, # [from,to),只要有一個即可
"key": "12歲以下" #區間別名,類似于sql查詢結果集的字段別名,非必需
},
{
"from": 12,
"to": 18,
"key": "12~18歲"
},
{
"from": 18,
"key": "18歲以上"
}
]
}
}
},
"size": 0
}
#按時間日期劃分桶
* year(1y)年
* quarter(1q)季度
* month(1M)月份
* week(1w)星期
* day(1d)天
* hour(1h)小時
* minute(1m)分鐘
* second(1s)秒
"query": {
"bool": {
"must": [{
"range": {
"@timestamp": {
"gte": 1533556800000,
"lte": 1533806520000
}
}
}]
}
},
// 不顯示具體的內容
"size": 0,
// 聚合
"aggs": {
// 自己取的聚合名字
"group_by_grabTime": {
// es提供的時間處理函數
"date_histogram": {
// 需要聚合分組的字段名稱, 類型需要為date, 格式沒有要求
"field": "@timestamp",
// 按什么時間段聚合, 這里是5分鐘, 可用的interval在上面給出
"interval": "5m",
// 設置時區, 這樣就相當于東八區的時間
"time_zone":"+08:00",
// 返回值格式化,HH大寫,不然不能區分上午、下午
"format": "yyyy-MM-dd HH",
// 為空的話則填充0
"min_doc_count": 0,
// 需要填充0的范圍
"extended_bounds": {
"min": 1533556800000,
"max": 1533806520000
}
},
// 聚合
"aggs": {
// 自己取的名稱
"group_by_status": {
// es提供
"terms": {
// 聚合字段名
"field": "LowStatusOfPrice"
}
}
}
}
}
```
<br>
## 指標聚合
常用的聚合函數
* value_count 該字段有值(不為空)的文檔數
* max 最大值
* min 最小值
* avg 平均值
* sum 總量
* stats 同時統計以上5個指標
* extended\_stats 統計更多的信息,比如平?和、?差、標準差
* cardinality 去重計數
```
#對全樣數據進行聚合,eg. 統計nba球員的平均年齡
GET /nba/_search
{
"aggs": {
"avg_age": { #自定義的聚合名稱
"avg": { #要使用的聚合函數
"field": "age" #要統計的字段
}
}
},
"size": 0
}
#對查詢結果進行聚合,eg. 統計?箭隊球員的平均年齡
GET /nba/_search
{
"query": {
"term": {
"team_name": "火箭隊"
}
},
"aggs": {
"avgAge": {
"avg": {
"field": "age"
}
}
},
"size": 0
}
#去重計數,eg. 統計某個活動的中獎人數
POST /raffle/_search
{
"query": {
"term": {
"activity_id": 123
}
},
"aggs": {
"coun_user": {
"cardinality": {
"field": "user_id"
}
}
},
"size": 0
}
```
<br>
## 嵌套聚合
```
#桶聚合嵌套指標聚合。先桶聚合按球隊劃分球員,再指標聚合得到每只球隊球員的平均年齡,再按平均年齡對桶進行排序
GET /nba/_search
{
"aggs": {
"team_avg_age": {
"terms": {
"field": "team_name",
"order": {
"avg_age": "asc" #avg_age是年齡聚合的名稱
}
},
"aggs": {
"avg_age": {
"avg": {
"field": "age"
}
}
}
}
},
"size": 0
}
#桶嵌套桶。先按省份劃分用戶,再在每個桶中按城市劃分
GET /user/_search
{
"aggs": {
"count_province": {
"terms": {
"field": "province"
},
"aggs": {
"count_province_city": {
"terms": {
"field": "city"
}
}
}
}
},
"size": 0
}
```
<br>
## 百分比
```
#查看學生成績的分布情況
POST /student/_search
{
"aggs": {
"percent_score": {
"percentiles": {
"field": "score",
"percents": [25, 50, 75] #指定百分比的分數,缺省時默認為 [1.0, 5.0, 25.0, 50.0, 75.0, 95.0, 99.0]
}
}
},
"size": 0
}
```
<br>
## 圖表
```
#eg. 統計學生成績的分布情況。也屬于桶聚合
GET /student/_search
{
"aggs":{
"socre_info":{
"histogram":{
"field": "score",
"interval": 20 #指定間距。[0,20),[20,40)...一個區間一個桶,區間上有文檔時才劃分為桶
}
}
},
"size" : 0
}
#按成績劃分區間(桶),統計每個區間上的文檔,再計算每個桶內的平均分。桶聚合+指標聚合
GET /student/_search
{
"aggs": {
"socre_info": {
"histogram": {
"field": "score",
"interval": 20
},
"aggs": {
"avg_score": {
"avg": {
"field": "score"
}
}
}
}
},
"size": 0
}
```