Mengubah data menjadi insight: metrics aggregations (sum, avg, stats, cardinality, percentiles), bucket aggregations (terms, histogram, date_histogram, range, nested), dan pipeline aggregations (moving average, derivative, cumulative sum) dengan bucket sorting.

Pencarian menjawab "dokumen mana yang cocok". Tapi bisnis tidak bertanya begitu saja — mereka bertanya "berapa total penjualan bulan ini?", "kategori apa yang paling laku?", "berapa harga rata-rata per kategori?". Jawabannya bukan kumpulan dokumen, melainkan agregasi: perhitungan statistik yang berjalan langsung di dalam Elasticsearch, tanpa memindahkan data ke aplikasi. Episode 9 membahas aggregation — salah satu fitur yang membuat Elasticsearch unik: metrics (sum, avg, min, max, stats, cardinality, percentiles), bucket (terms, histogram, date_histogram, range, nested), dan pipeline (moving average, derivative, cumulative sum, bucket sorting). Dengan ini kalian bisa membangun dashboard analytics tanpa tool tambahan.
Aggregation dikirim bersama query di blok aggs lewat POST /produk/_search. Semua hit yang cocok dengan query dikelompokkan, dan setiap aggregation menghitung hasilnya. Contoh paling sederhana:
{ "size": 0, "aggs": { "rata_harga": { "avg": { "field": "price" } } } }Perhatikan "size": 0 — kita tidak butuh dokumennya, hanya hasil agregasinya. Ini pola standar: query untuk menentukan data apa, aggregation untuk menentukan apa yang dihitung.
Metrics menghitung nilai dari semua dokumen yang cocok:
| Aggregation | Fungsi |
|---|---|
sum, avg, min, max | Operasi dasar |
stats | Gabungan count, min, max, avg, sum dalam satu aggregation |
extended_stats | Menambah variance, std_deviation, sum_of_squares |
cardinality | Jumlah nilai unik (seperti COUNT DISTINCT) |
percentiles | Distribusi nilai, misal median dan p99 |
percentile_ranks | Berapa persen nilai di bawah ambang tertentu |
value_count | Menghitung jumlah nilai (termasuk menangani null) |
{
"size": 0,
"aggs": {
"harga_stats": { "stats": { "field": "price" } },
"merek_unik": { "cardinality": { "field": "brand.keyword" } },
"harga_percentiles": { "percentiles": { "field": "price" } }
}
}cardinality berguna untuk metrik "jumlah pengguna unik per hari" tanpa menyimpan semua ID; percentiles menjawab "harga berapa yang ada di atas 90% produk lain" — dasar fitur filter harga di e-commerce.
Tip
cardinality berjalan di field keyword atau doc_values numerik. Ingat: cardinality memakai algoritma estimasi (HyperLogLog) — nilainya akurat hingga ribuan, dengan error kecil di skala sangat besar. Untuk kebutuhan persis, siapkan field dengan doc_values: true dan hindari field text yang tidak punya doc values.
Bucket mengelompokkan dokumen ke dalam kategori — lalu di dalam tiap bucket bisa dijalankan aggregation lagi. Ini konsep GROUP BY-nya Elasticsearch.
terms mengelompokkan berdasarkan nilai unik field keyword:
{
"size": 0,
"aggs": { "per_kategori": { "terms": { "field": "category.keyword", "size": 10 } } }
}Hasilnya daftar kategori diurutkan berdasarkan jumlah dokumen. Default hanya mengambil top 10 — atur size lebih besar jika butuh lebih banyak.
histogram mengelompokkan numerik ke dalam interval tetap; date_histogram melakukan hal yang sama untuk rentang waktu — aggregation paling penting untuk data time-series:
{
"size": 0,
"aggs": {
"per_bulan": {
"date_histogram": { "field": "@timestamp", "calendar_interval": "month" },
"aggs": { "total_penjualan": { "sum": { "field": "amount" } } }
}
}
}Ini adalah pola standar untuk grafik "penjualan per bulan" di dashboard — query dan aggregation berjalan dalam satu request.
range mengelompokkan berdasarkan interval yang kita tentukan sendiri, misalnya segmen harga:
{
"size": 0,
"aggs": {
"segmen_harga": {
"range": { "field": "price", "ranges": [ { "to": 50000 }, { "from": 50000, "to": 100000 }, { "from": 100000 } ] }
}
}
}Aggregation bisa bertumpuk — bucket di dalam bucket. Contoh: jumlah produk per kategori, dan di dalam tiap kategori, rata-rata harga:
{
"size": 0,
"aggs": { "per_kategori": { "terms": { "field": "category.keyword" }, "aggs": { "rata_harga": { "avg": { "field": "price" } } } } }
}Jika field bertipe nested, gunakan blok nested khusus agar aggregation menghormati batas antar objek — di episode 5 kita bahas kenapa ini penting.
Pipeline aggregation bekerja di atas hasil bucket lain, bukan dokumen mentah. Ini yang memungkinkan analisis deret waktu.
{
"size": 0,
"aggs": {
"per_bulan": {
"date_histogram": { "field": "@timestamp", "calendar_interval": "month" },
"aggs": { "total_penjualan": { "sum": { "field": "amount" } }, "rata_gerak": { "moving_avg": { "buckets_path": "total_penjualan" } }, "perubahan": { "derivative": { "buckets_path": "total_penjualan" } } }
},
"kumulatif": { "cumulative_sum": { "buckets_path": "per_bulan>total_penjualan" } }
}
}moving_avg — menghaluskan fluktuasi, bagus untuk mendeteksi tren di balik data berisik.derivative — menghitung laju perubahan antar bucket (penjualan naik/turun).cumulative_sum — akumulasi bertahap, misal total kumulatif tahun ini.bucket_sort pipeline.significant_terms adalah bucket aggregation yang menarik: ia menemukan nilai field yang sangat tidak biasa dibandingkan latar belakang seluruh data. Contohnya: di antara produk yang terjual minggu ini, merek apa yang proporsinya melonjak dibanding tren normal? Ini dasar untuk fitur "trending" dan deteksi anomali sederhana.
{
"size": 0,
"query": { "range": { "@timestamp": { "gte": "now-7d" } } },
"aggs": { "merek_trending": { "significant_terms": { "field": "brand.keyword" } } }
}Hasilnya daftar merek yang secara statistik paling "menonjol" di subset data ini — tanpa perlu tahu definisi trending sebelumnya.
Warning
Aggregation yang berat — terutama terms dengan size besar, cardinality di data raksasa, atau pipeline berjenjang — bisa menekan memori node. Batasi size bucket sesuai kebutuhan dashboard, dan ingat aggregation berjalan di memori JVM. Episode 19 akan membahas cara menyetel resource untuk aggregation berat.
Lupa size: 0. Jika tidak, Elasticsearch tetap mengembalikan dokumen hit yang tidak kalian butuhkan — boros bandwidth dan memori.
Aggregation di field text. Aggregation butuh doc_values — gunakan keyword sub-field, bukan text.
terms dengan size default. Default 10 bucket bisa menyesatkan. Set size eksplisit sesuai kebutuhan.
Date histogram interval tidak cocok dengan granularitas data. calendar_interval dan fixed_interval berbeda tujuannya — pilih sesuai, jangan asal "1d" untuk semua.
Pipeline aggregation tanpa buckets_path yang benar. Path harus menunjuk aggregation anak secara hierarkis, misal per_bulan>total_penjualan.
Di episode 9 kalian menguasai aggregation: metrics (sum, avg, min, max, stats, extended_stats, cardinality, percentiles, percentile_ranks), bucket (terms, histogram, date_histogram, range, nested, significant_terms), dan pipeline (moving_avg, derivative, cumulative_sum, bucket_sort) — lengkap dengan pola bucket-bertumpuk untuk dashboard analytics.
Inti yang harus dibawa pulang:
size: 0 bila hanya butuh hasil aggregation, bukan dokumen.date_histogram adalah fondasi analisis deret waktu.significant_terms menemukan nilai yang tidak biasa secara statistik.Sekarang data bisa disimpan, dicari, dan dianalisis. Saatnya berpikir tentang siklus hidup data. Di episode 10 kita bahas Index Lifecycle Management (ILM): arsitektur hot-warm-cold-frozen, rollover, fase-fase ILM, index priority, allocation filtering, pembuatan policy, dan searchable snapshots untuk tier frozen. Sampai jumpa!