Elasticsearch Bài học 38: Pipeline Aggregations - Tính toán phái sinh (Thống kê của bảng thống kê)
Trong hai bài trước, chúng ta đã chia được giỏ dữ liệu (Bucket) và đếm được tiền trong từng giỏ (Metric). Nhưng hãy tưởng tượng sếp của bạn (hoặc Data Analyst) nhìn vào biểu đồ doanh thu theo từng tháng và hỏi một câu cực kỳ hóc búa:
"Tôi không muốn xem số tuyệt đối. Hãy vẽ cho tôi biểu đồ Tốc độ tăng trưởng doanh thu so với tháng trước. Tháng nào tăng thì màu xanh, giảm thì màu đỏ. Và tìm ra cho tôi cái tháng có doanh thu cao nhất năm."
Bài toán này vượt quá giới hạn của Aggregations thông thường, bởi vì Metric và Bucket chỉ làm việc trực tiếp với các Document tĩnh. Để giải quyết câu hỏi trên, bạn cần tính toán sự chênh lệch GIỮA CÁC BUCKET VỚI NHAU.
Đó chính là sân khấu của Pipeline Aggregations. Nó không đọc Document, nó đọc kết quả của các Aggregations khác đã chạy trước đó.
1. Cú pháp buckets_path: Chìa khóa để lấy dữ liệu
Để Pipeline Aggregation biết nó phải lấy dữ liệu từ đâu để tính toán, chúng ta dùng tham số buckets_path. Cú pháp của nó rất giống việc bạn truy cập vào đường dẫn thư mục trong Linux: tên_bucket_cha>tên_metric_con.
Có 2 họ Pipeline chính:
-
Parent Pipeline: Nằm bên trong một Bucket (để xử lý dữ liệu của chính Bucket đó).
-
Sibling Pipeline: Nằm bên cạnh (ngang hàng) với các Bucket khác (để đánh giá tổng thể tất cả các Bucket).
2. Derivative (Đạo hàm): Tính tốc độ tăng trưởng
Đạo hàm trong Toán học thể hiện tốc độ thay đổi (Rate of change). Trong Elasticsearch, hàm derivative sẽ tính chênh lệch giá trị của Bucket hiện tại trừ đi Bucket ngay trước đó.
Nghiệp vụ: Tính doanh thu theo từng tháng, sau đó tính mức tăng/giảm doanh thu so với tháng trước.
JSON
GET orders/_search
{
"size": 0,
"aggs": {
"doanh_thu_theo_thang": {
"date_histogram": {
"field": "created_at",
"calendar_interval": "1M"
},
"aggs": {
"tong_tien": {
"sum": { "field": "total_amount" }
},
"muc_tang_truong": {
"derivative": {
"buckets_path": "tong_tien"
}
}
}
}
}
}
Cách nó chạy:
-
Tháng 1: Doanh thu 100tr. Mức tăng trưởng:
null(Vì không có tháng trước để trừ). -
Tháng 2: Doanh thu 120tr. Mức tăng trưởng:
120 - 100 = 20tr. -
Tháng 3: Doanh thu 90tr. Mức tăng trưởng:
90 - 120 = -30tr.Từ kết quả này, Frontend có thể dễ dàng vẽ biểu đồ cột xanh (tăng) và đỏ (giảm).
3. Moving Average (Trung bình trượt): Làm mượt biểu đồ
Trong hệ thống E-commerce thực tế, doanh thu theo ngày thường nhảy múa "răng cưa" cực kỳ gắt (Thứ 7, CN vọt lên, Thứ 2, Thứ 3 cắm đầu xuống). Nếu đưa sếp xem biểu đồ răng cưa này, rất khó để nhận ra xu hướng (Trend) đang đi lên hay đi xuống.
Hàm moving_fn (hàm kế thừa của moving_avg) giúp bạn tính trung bình cộng của N ngày gần nhất, làm "mượt" (smooth) biểu đồ lại.
JSON
"aggs": {
"doanh_thu_theo_ngay": {
"date_histogram": {
"field": "created_at",
"calendar_interval": "1d"
},
"aggs": {
"tong_tien": { "sum": { "field": "total_amount" } },
"trung_binh_7_ngay": {
"moving_fn": {
"buckets_path": "tong_tien",
"window": 7, // Lấy trung bình cộng của 7 ngày gần nhất
"script": "MovingFunctions.unweightedAvg(values)"
}
}
}
}
}
4. max_bucket / min_bucket: Tìm ra "Quán quân"
Quay lại với yêu cầu thứ hai của sếp: "Tháng nào có doanh thu cao nhất năm?"
Thay vì trả về 12 tháng rồi bắt code Backend tự dùng vòng lặp for để tìm số Max, Elasticsearch có thể tự làm điều đó bằng max_bucket (Một Sibling Pipeline nằm ngang hàng với Date Histogram).
JSON
GET orders/_search
{
"size": 0,
"aggs": {
"doanh_thu_theo_thang": {
"date_histogram": {
"field": "created_at",
"calendar_interval": "1M"
},
"aggs": {
"tong_tien": { "sum": { "field": "total_amount" } }
}
},
"thang_cao_nhat": { // Ngang hàng với doanh_thu_theo_thang
"max_bucket": {
"buckets_path": "doanh_thu_theo_thang>tong_tien"
}
}
}
}
Kết quả trả về sẽ có thêm một block cung cấp chính xác Tháng chiến thắng và Doanh thu của nó:
JSON
"thang_cao_nhat": {
"value": 150000000.0,
"keys": ["2026-12-01T00:00:00.000Z"]
}
Nhờ có Pipeline Aggregations, Elasticsearch thực sự vượt xa giới hạn của một cỗ máy Full-text search để trở thành một Data Warehouse mini thời gian thực (Real-time).
Tuy nhiên, chạy Aggregations trên 50 triệu bản ghi vẫn là một công việc tiêu tốn rất nhiều CPU. Ở các bài học sau, chúng ta sẽ tối ưu hóa câu query bằng Filter Aggregations để giảm thiểu lượng dữ liệu phải tính toán, trước khi bước vào Module Quản trị hệ thống (Production-Ready).
All rights reserved