Trích xuất dữ liệu từ mảng object lồng nhau
Kết hợp $unwind (flatten mảng) + $match (lọc) + $group (gộp) để lấy giá trị từ mảng object phức tạp.
1. Dữ liệu: mảng Information chứa object có mảng details
> db.demo459.insertOne({
_id: 1,
Information: [
{ Name: "Chris", _id: new ObjectId(), details: ["HR"] },
{ Name: "David", _id: new ObjectId(), details: ["Developer"] },
{ Name: "Bob", _id: new ObjectId(), details: ["Account"] }
]
});
{ "acknowledged": true, "insertedId": 1 }
2. Pipeline: Lấy details của Chris và Bob
> db.demo459.aggregate([
{ $unwind: "$Information" }, // Tách mảng Information
{ $unwind: "$Information.details" }, // Tách mảng details bên trong
{ $match: { 'Information.Name': { $in: ["Chris", "Bob"] } } }, // Lọc tên
{ $group: { _id: null, detailList: { $addToSet: "$Information.details" } } } // Gộp unique
]);
3. Kết quả
{ "_id": null, "detailList": ["Account", "HR"] }
Giải thích từng bước
- $unwind "$Information": 1 doc → 3 doc (mỗi object trong mảng)
- $unwind "$Information.details": Mỗi doc → n doc (mỗi string trong details)
- $match: Chỉ giữ doc có Name = Chris hoặc Bob
- $group + $addToSet: Gộp lại, loại trùng lặp (Set)
Biến thể: Giữ cả tên người
db.demo459.aggregate([
{ $unwind: "$Information" },
{ $unwind: "$Information.details" },
{ $match: { 'Information.Name': { $in: ["Chris", "Bob"] } } },
{ $group: {
_id: "$Information.Name",
details: { $addToSet: "$Information.details" }
} }
]);
// Kết quả: { "_id": "Chris", "details": ["HR"] }, { "_id": "Bob", "details": ["Account"] }
Mẹo hiệu suất
- Đặt
$matchsớm nhất có thể (trước $unwind nếu lọc trường gốc) - Dùng
$addToSetthay$pushkhi muốn unique - Với mảng lớn, cân nhắc
$projectchỉ giữ trường cần thiết trước $unwind