Menggunakan Query Aggregate di Elasticsearch

Muhammad Arslan 6 Januari 2017

Menggunakan Query Aggregate di Elasticsearch

Agregasi tentu dibutuhkan oleh seseorang untuk menampilkan informasi yang lebih ringkas sesuai dengan kebutuhan waktu tertentu. Misal kita ingin melihat banyaknya pekerja berdasarkan jenis kelamin, pekerja berdasarkan rentang umur, atau mencari maksimal gaji yang diterima seorang pekerja.

Elasticsearch memberikan sejumlah filter dan query yang memudahkan penggunanya untuk melakukan agregasi, ada yang berupa histogram ada juga yang dapat merangkum semua agregasi dasar (max, min, avg, sum) sekaligus.

Untuk lebih jelasnya mari kita ikuti tutorial ini.goo

1. Persiapan

Contoh data yang akan kita gunakan adalah data account yang dirilis oleh Elasticsearch untuk latihan query. Kamu dapat mengunduhnya di tautan berikut: accounts.json. Sedangkan untuk memasangnya di localhost, silahkan ikuti command berikut:
curl -XPUT http://localhost:9200/demo
curl -XPUT http://localhost:9200/demo/account/_bulk?pretty=true --data-binary '@accounts.json'
Disana kita simpan types account di dalam indeks demo. Selanjutnya kita akan bermain - main dengan berbagai query agregasi yang dimiliki oleh Elasticsearch. Untuk memeriksa apakah data account sudah terindeks silahkan akses URL http://localhost:9200/demo/account/_mapping:
{
    "demo": {
        "mappings": {
            "account": {
                "properties": {
                    "account_number": {
                        "type": "long"
                    },
                    "address": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "age": {
                        "type": "long"
                    },
                    "balance": {
                        "type": "long"
                    },
                    "city": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "email": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "employer": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "firstname": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "gender": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "lastname": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    },
                    "state": {
                        "type": "text",
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    }
                }
            }
        }
    }
}

2. Menggunakan extended_stats

Cukup repot juga kan bila kita harus membuat query yang agak panjang hanya untuk mencari max, min, avg, sum, standard deviasi, dan varians? Elasticsearch memiliki query yang cukup praktis untuk mendapatkan informasi tersebut terhadap suatu field. Silahkan buat file dengan nama query.json, kemudian buat struktur query berikut di dalam file tersebut:
{   
    "size":0,
    "query":{
        "match_all":{}
    },
    "aggregations":{
        "age_stats":{
            "extended_stats":{
                "field":"age"
            }
        },
        "balance_stats":{
            "extended_stats":{
                "field":"balance"
            }
        }
    }
}
Pada intinya kita akan mengambil informasi agregasi dari dua field yaitu age dan balance. Bila kita jalankan query diatas maka akan muncul output seperti berikut:
$ curl -XGET http://localhost:9200/demo/account/_search?pretty=true -d '@query.json'
{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "age_stats" : {
      "count" : 1000,
      "min" : 20.0,
      "max" : 40.0,
      "avg" : 30.171,
      "sum" : 30171.0,
      "sum_of_squares" : 946393.0,
      "variance" : 36.10375899999996,
      "std_deviation" : 6.008640362012022,
      "std_deviation_bounds" : {
        "upper" : 42.18828072402404,
        "lower" : 18.153719275975956
      }
    },
    "balance_stats" : {
      "count" : 1000,
      "min" : 1011.0,
      "max" : 49989.0,
      "avg" : 25714.837,
      "sum" : 2.5714837E7,
      "sum_of_squares" : 8.58626807735E11,
      "variance" : 1.9737396579843104E8,
      "std_deviation" : 14048.984511288745,
      "std_deviation_bounds" : {
        "upper" : 53812.80602257749,
        "lower" : -2383.1320225774907
      }
    }
  }
}

Mudah untuk digunakan bukan :D?

3. Menggunakan terms

Selanjutnya kita ingin mencari berapa banyak pekerja berdasarkan jenis kelamin. Karena jenis kelamin adalah data berupa keyword maka kita gunakan terms untuk menghitungnya.
{   
    "size":0,
    "query":{
        "match_all":{}
    },
    "aggregations":{
        "gender_stats":{
            "terms":{
                "field":"gender.keyword"
            }
        }
    }
}
Bila dijalankan maka akan muncul informasi dimana kita dapat melihat banyaknya pekerja berdasarkan jenis kelamin M dan F
$ curl -XGET http://localhost:9200/demo/account/_search?pretty=true -d '@query.json'
{
  "took" : 28,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "gender_stats" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "M",
          "doc_count" : 507
        },
        {
          "key" : "F",
          "doc_count" : 493
        }
      ]
    }
  }
}

4. Menggunakan range

Kamu juga dapat melakukan query agregasi dengan membaginya berdasarkan rentang tertentu. Kamu dapat dengan bebas menentukan berapa banyak rentang dan berapa nilai terendah dan tertinggi dari suatu rentang. Coba buat query berikut pada file query.json:
{   
    "size":0,
    "query":{
        "match_all":{}
    },
    "aggregations":{
        "age_range_stats":{
            "range":{
                "field":"age",
                "ranges":[
                    {"to":10},
                    {"from":10, "to":20},
                    {"from":20, "to":30},
                    {"from":30, "to":40},
                    {"from":50, "to":60},
                    {"from":70}
                ]
            }
        }
    }
}
Bila dijalankan maka akan muncul informasi dimana kita dapat melihat banyaknya pekerja berdasarkan rentang umur yang telah didefinisikan
$ curl -XGET http://localhost:9200/demo/account/_search?pretty=true -d '@query.json'
{
  "took" : 11,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "age_range_stats" : {
      "buckets" : [
        {
          "key" : "*-10.0",
          "to" : 10.0,
          "doc_count" : 0
        },
        {
          "key" : "10.0-20.0",
          "from" : 10.0,
          "to" : 20.0,
          "doc_count" : 0
        },
        {
          "key" : "20.0-30.0",
          "from" : 20.0,
          "to" : 30.0,
          "doc_count" : 451
        },
        {
          "key" : "30.0-40.0",
          "from" : 30.0,
          "to" : 40.0,
          "doc_count" : 504
        },
        {
          "key" : "50.0-60.0",
          "from" : 50.0,
          "to" : 60.0,
          "doc_count" : 0
        },
        {
          "key" : "70.0-*",
          "from" : 70.0,
          "doc_count" : 0
        }
      ]
    }
  }
}
Walaupun key-nya agak aneh, tapi kamu dapat dengan mudah mengambil informasi yang cukup mudah bila ingin melihat rentang data.

5. Menggunakan histogram

Hampir sama dengan range, namun histogram lebih mudah karena pembaginya adalah interval nilai suatu field. Kamu dapat menentukan besaran interval berdasarkan kebutuhan. Sebagai contoh coba ikuti query berikut. Buat query berikut ke dalam file query.json
{   
    "size":0,
    "query":{
        "match_all":{}
    },
    "aggregations":{
        "age_stats":{
            "histogram":{
                "field":"age",
                "interval":5
            }
        },
        "balance_stats":{
            "histogram":{
                "field":"balance",
                "interval":5000
            }
        }
    }
}
Bila dijalankan maka akan muncul informasi dimana kita dapat melihat banyaknya pekerja berdasarkan interval yang telah ditentukan di masing - masing field.
$ curl -XGET http://localhost:9200/demo/account/_search?pretty=true -d '@query.json'
{
  "took" : 22,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 1000,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "age_stats" : {
      "buckets" : [
        {
          "key" : 20.0,
          "doc_count" : 225
        },
        {
          "key" : 25.0,
          "doc_count" : 226
        },
        {
          "key" : 30.0,
          "doc_count" : 259
        },
        {
          "key" : 35.0,
          "doc_count" : 245
        },
        {
          "key" : 40.0,
          "doc_count" : 45
        }
      ]
    },
    "balance_stats" : {
      "buckets" : [
        {
          "key" : 0.0,
          "doc_count" : 79
        },
        {
          "key" : 5000.0,
          "doc_count" : 89
        },
        {
          "key" : 10000.0,
          "doc_count" : 111
        },
        {
          "key" : 15000.0,
          "doc_count" : 102
        },
        {
          "key" : 20000.0,
          "doc_count" : 104
        },
        {
          "key" : 25000.0,
          "doc_count" : 113
        },
        {
          "key" : 30000.0,
          "doc_count" : 92
        },
        {
          "key" : 35000.0,
          "doc_count" : 95
        },
        {
          "key" : 40000.0,
          "doc_count" : 121
        },
        {
          "key" : 45000.0,
          "doc_count" : 94
        }
      ]
    }
  }
}

6. Referensi

  • Elasticsearch official documentation
  • Tutorialspoint - Elasticsearch
(arslan/elasticsearch)