iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 29
0
Elastic Stack on Cloud

Python&Elasticsearch 入門系列 第 29

IT鐵人第29天 Elasticsearch 使用python查詢資料 Aggregations:Terms

今天的文章要介紹的是Bucket Aggregations的一種聚合方式,其實Metrics Aggregations還有很多種聚合方式沒講完,但因為剩下兩天了所以想把這個我比較常用的聚合方式告訴大家

這次的測試資料:
https://ithelp.ithome.com.tw/upload/images/20201012/20129976vJOw4N9OFe.png

Terms

・這種聚合方式會根據指定字段的每個唯一值形成一個桶,在歷遍所有文檔根據指定字段的值丟到相應的桶裡面執行收集

・預設情況會返回前10名的桶,可以透過可調參數size調整

・一般情況下ES會透過分片搜集,每個分片會回傳前幾size個的桶(size=1就回傳分片中最多數量的桶),再將分辨結果合併減少到變成最終的列表,再回傳給客戶端。如果唯一值大於size,返回的列表可能會跟現實有點偏離,導致出來的結果不是很正確,聽起來很抽象,我直接用例子說明

size=3

分片1

top1 "鐵" 10
top2 "人" 8
top3 "賽" 7
top4 "IT" 6
回傳"鐵"、"人"、"賽"

分片2

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”的桶,然後再進行收集

・show_term_doc_count_error

這是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
      }
    ]
  }
}

・min_doc_count

限制最低數量
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" : [ ]
  }
}

・order

設定結果回傳時的排序方式,預設是照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
        }
      }
    ]
  }
}

・script

可以使用腳本來組合字段再統計數量
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
      }
    ]
  }
}

include/exclude

可以藉由這兩個可調參數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

這個單次請求如果要處理的唯一值太多時,可以使用這兩個可調參數拆解成多份,在請求時針對一份做處理
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
        }
      ]
    }
  }

今天的文章就到這邊,謝謝大家


上一篇
IT鐵人第28天 Elasticsearch 使用python查詢資料 Aggregations:Sum/Value Count
下一篇
IT鐵人第30天 Elasticsearch 使用python查詢資料 Aggregations:Scripted Metric
系列文
Python&Elasticsearch 入門30

尚未有邦友留言

立即登入留言