Aggregation mảng lồng nhiều cấp (nested array)
Xử lý mảng lồng sâu với $map, $let, $arrayElemAt, $cond để trích xuất và biến đổi dữ liệu.
1. Dữ liệu phức tạp: mảng details → mảng details1
> db.demo441.insertOne({
Name: "David", Age: 21,
details: [{
id: 1, CountryName: "US",
details1: [
{ SubjectName: "MySQL", Score: 56 },
{ SubjectName: "MongoDB", Score: 78 }
]
}]
});
{ "acknowledged": true, "insertedId": ObjectId("5e78cc05bbc41e36cc3caeb7") }
2. Pipeline aggregation
> db.demo441.aggregate([{
$addFields: {
ResultOfDetails: {
$map: {
input: "$details",
as: "output",
in: {
id: "$$output.id",
CountryName: "$$output.CountryName",
details1: {
$let: {
vars: {
last: { $arrayElemAt: ["$$output.details1", -1] }
},
in: {
$cond: [
{ $eq: ["$$last.Score", 78] },
["$$last"],
[]
]
}
}
}
}
}
}
}
}]).pretty();
3. Kết quả
{
"_id": ObjectId("5e78cc05bbc41e36cc3caeb7"),
"Name": "David", "Age": 21,
"details": [{ "id": 1, "CountryName": "US", "details1": [{ "SubjectName": "MySQL", "Score": 56 }, { "SubjectName": "MongoDB", "Score": 78 }] }],
"ResultOfDetails": [{
"id": 1, "CountryName": "US",
"details1": [{ "SubjectName": "MongoDB", "Score": 78 }]
}]
}
Giải thích các toán tử chính
| Toán tử | Chức năng |
|---|---|
| $map | Duyệt mảng, biến đổi từng phần tử |
| $let | Định nghĩa biến cục bộ (vars) để tái sử dụng |
| $arrayElemAt | Lấy phần tử tại index (index âm = từ cuối) |
| $cond | If-then-else: điều kiện, true-case, false-case |
Logic ví dụ này
- Duyệt qua mảng
details - Với mỗi item, lấy phần tử cuối cùng của
details1(index -1) - Nếu
Score == 78→ giữ phần tử đó, ngược lại → mảng rỗng - Tạo trường mới
ResultOfDetailschứa kết quả biến đổi
Mẹo: Với mảng lồng sâu, hãy phân tích từng cấp độ và dùng $unwind nếu cần flatten trước khi xử lý.