Phase $group trong Aggregation thường tốn tài nguyên nhất (bộ nhớ, CPU) vì phải gom nhóm toàn bộ dữ liệu. Để **tăng tốc $group**, nguyên tắc cốt lõi là **giảm thiểu dữ liệu đầu vào** trước khi group: lọc sớm ($match), chiếu trường cần thiết ($project), và tận dụng index.
1. Tạo dữ liệu: 1 tài liệu chứa mảng 10 số
> db.demo423.insertOne({ "Information": [101, 110, 87, 110, 98, 115, 101, 115, 89, 115] });
2. Pipeline tối ưu: Tìm 2 giá trị xuất hiện nhiều nhất (Top 2 Frequency)
> db.demo423.aggregate([
{ $project: { _id: 0, Information: 1 } }, // 1. Chỉ lấy trường cần thiết (giảm payload)
{ $unwind: "$Information" }, // 2. Bật mảng thành stream các số
{ $group: { _id: "$Information", frequency: { $sum: 1 } } }, // 3. Group đếm tần suất
{ $sort: { frequency: -1 } }, // 4. Sắp xếp giảm dần theo tần suất
{ $limit: 2 } // 5. Chỉ lấy top 2 (giảm output)
]);
3. Kết quả
{ "_id": 115, "frequency": 3 }
{ "_id": 110, "frequency": 2 }
Các kỹ thuật tối ưu $group:
- $match đầu tiên: Lọc document trước khi $unwind/$group (dùng index).
- $project sớm: Chỉ giữ trường cần group/sort, bỏ _id, trường lớn không dùng.
- Allow Disk Use: Nếu group lớn > 100MB RAM, thêm
{ allowDiskUse: true }để spill ra disk (chậm hơn nhưng không crash). - Index hỗ trợ: Index trên trường $match/$sort giúp giảm input vào $group.
- $limit sớm: Nếu chỉ cần top N, $limit sau $sort (như ví dụ).
- Tránh $group lồng nhau: Dùng $facet hoặc restructure data.
Lưu ý: Ví dụ gốc chỉ có 1 document -> $unwind tạo 10 doc -> group nhẹ. Thực tế collection lớn thì $match/$project đầu tiên cực quan trọng.