今天的文章要介紹的是Bucket Aggregations的一種聚合方式,其實Metrics Aggregations還有很多種聚合方式沒講完,但因為剩下兩天了所以想把這個我比較常用的聚合方式告訴大家
這次的測試資料:
・這種聚合方式會根據指定字段的每個唯一值形成一個桶,在歷遍所有文檔根據指定字段的值丟到相應的桶裡面執行收集
・預設情況會返回前10名的桶,可以透過可調參數size調整
・一般情況下ES會透過分片搜集,每個分片會回傳前幾size個的桶(size=1就回傳分片中最多數量的桶),再將分辨結果合併減少到變成最終的列表,再回傳給客戶端。如果唯一值大於size,返回的列表可能會跟現實有點偏離,導致出來的結果不是很正確,聽起來很抽象,我直接用例子說明
size=3
top1 "鐵" 10
top2 "人" 8
top3 "賽" 7
top4 "IT" 6
回傳"鐵"、"人"、"賽"
top1 "IT" 5
top2 "人" 4
top3 "鐵" 3
top4 "賽" 2
回傳"IT"、"人"、"鐵"
最終返回結果
top1 "鐵":13個、top2 "人":12個、top3 "賽":7個
可以看到原本的"IT"應該是top3(11個),但因為他在分片1裡排在top4超出了我們所設定的size=3所以沒回傳,而結果也可以看到賽從原本的9個變成7個,這邊是在設定size時所要注意的部分
先設定一個目標,假設想知道有哪些班級且人數有多少
aggs query:
{
"aggs": {
"class_num": {
"terms": {
"field": "class",
"size": 10
}
}
}
}
結果:
"aggregations" : {
"class_num" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "資工一1",
"doc_count" : 3
},
{
"key" : "資工一2",
"doc_count" : 3
}
]
}
}
ES內部會先建立“資工一1”的桶跟“資工一2”的桶,然後再進行收集
這是terms聚合的可調參數,將這個參數設為True將會多回傳一個值,這個值代表該唯一值最大潛在數量,但沒有被計入最終結果中
aggs query:
"aggs": {
"class_num": {
"terms": {
"field": "class",
"size": 10,
"show_term_doc_count_error": true
}
}
}
結果:
"aggregations" : {
"class_num" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "資工一1",
"doc_count" : 3,
"doc_count_error_upper_bound" : 0
},
{
"key" : "資工一2",
"doc_count" : 3,
"doc_count_error_upper_bound" : 0
}
]
}
}
限制最低數量
aggs query:
{
"aggs": {
"class_num": {
"terms": {
"field": "class",
"size": 10,
"show_term_doc_count_error": true,
"min_doc_count": 10
}
}
}
}
結果:
"aggregations" : {
"class_num" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [ ]
}
}
設定結果回傳時的排序方式,預設是照doc_count排序
按字母進行排序
{
"aggs": {
"class_num": {
"terms": {
"field": "name",
"size": 10,
"order": {
"_key": "asc"
}
}
}
}
}
也可以指定一個單值的metric聚合來排序,例如以下利用各班的數學平均來排序
aggs query:
{
"aggs": {
"class_num": {
"terms": {
"field": "class",
"size": 10,
"order": {
"math_avg": "desc"
}
},
"aggs": {
"math_avg": {
"avg": {
"field": "grades.math"
}
}
}
}
}
}
結果:
"aggregations" : {
"class_num" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "資工一1",
"doc_count" : 3,
"math_avg" : {
"value" : 74.66666666666667
}
},
{
"key" : "資工一2",
"doc_count" : 3,
"math_avg" : {
"value" : 67.0
}
}
]
}
}
多值的metric聚合也可以,但是要指定字段
以下改為用最小值排序
aggs query:
{
"aggs": {
"class_num": {
"terms": {
"field": "class",
"size": 10,
"order": {
"math_avg.min": "desc"
}
},
"aggs": {
"math_avg": {
"stats": {
"field": "grades.math"
}
}
}
}
}
}
結果:
"aggregations" : {
"class_num" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "資工一1",
"doc_count" : 3,
"math_avg" : {
"count" : 3,
"min" : 60.0,
"max" : 91.0,
"avg" : 74.66666666666667,
"sum" : 224.0
}
},
{
"key" : "資工一2",
"doc_count" : 3,
"math_avg" : {
"count" : 3,
"min" : 34.0,
"max" : 91.0,
"avg" : 67.0,
"sum" : 201.0
}
}
]
}
}
可以使用腳本來組合字段再統計數量
aggs query:
{
"aggs": {
"class_num": {
"terms": {
"field": "class",
"size": 10,
"script": {
"lang": "painless",
"source": "doc['class'].value + doc['name'].value"
}
}
}
}
}
結果:
"aggregations" : {
"class_num" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "資工一1小新",
"doc_count" : 1
},
{
"key" : "資工一1王小明",
"doc_count" : 1
},
{
"key" : "資工一1風間",
"doc_count" : 1
},
{
"key" : "資工一2正男",
"doc_count" : 1
},
{
"key" : "資工一2許小美",
"doc_count" : 1
},
{
"key" : "資工一2阿呆",
"doc_count" : 1
}
]
}
}
可以藉由這兩個可調參數filter調設定的條件
假設今天我想找到資工所有班級但不想包含資工一2
aggs query:
{
"aggs": {
"class_num": {
"terms": {
"field": "class",
"size": 10,
"include": ".*資工.*",
"exclude": ".*一2.*"
}
}
}
}
結果:
"aggregations" : {
"class_num" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "資工一1",
"doc_count" : 3
}
]
}
}
這個單次請求如果要處理的唯一值太多時,可以使用這兩個可調參數拆解成多份,在請求時針對一份做處理
partition:指定這次的請求要針對哪一份做處理
num_partitions:要分成幾份
aggs query:
{
"aggs": {
"class_num": {
"terms": {
"field": "class",
"size": 10,
"include": {
"partition": 1,
"num_partitions": 3
}
}
}
}
}
結果:
"aggregations" : {
"class_num" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "資工一2",
"doc_count" : 3
}
]
}
}
今天的文章就到這邊,謝謝大家