Khi cần tìm kiếm sâu vào bên trong mảng các object (subdocuments) và trả về **chính xác phần tử khớp** (không phải toàn bộ tài liệu cha), cách tốt nhất là dùng **Aggregation Pipeline** với $unwind (bật mảng) + $match (lọc). Cách này linh hoạt hơn find() + positional operator.
1. Tạo bộ sưu tập: 1 tài liệu, mảng details chứa 2 sinh viên
> db.demo414.insertOne({
"_id": "110",
"details": [
{ "StudentName": "John", "StudentMarks": 56 },
{ "StudentName": "Robert", "StudentMarks": 98 }
]
});
{ "acknowledged": true, "insertedId": "110" }
2. Xem dữ liệu
> db.demo414.find();
Kết quả: 1 tài liệu, mảng details 2 phần tử.
3. Aggregation: Tìm phần tử có StudentMarks = 56
> db.demo414.aggregate([
{ $unwind: "$details" }, // Bật mảng: 1 doc -> 2 doc
{ $match: { "details.StudentMarks": 56 } } // Lọc phần tử khớp
]);
4. Kết quả: Chỉ phần tử khớp (details thành object, không còn mảng)
{ "_id": "110", "details": { "StudentName": "John", "StudentMarks": 56 } }
So sánh với find() + positional $:
find(): Trả về **toàn bộ tài liệu cha** (kèm mảng đầy đủ). Dùng$trong projection không được (chỉ dùng trong update).aggregate($unwind + $match): Trả về **chính xác phần tử con** khớp, có thể project thêm trường cha.
Mở rộng: Gom lại thành mảng (nếu cần): Thêm { $group: { _id: "$_id", details: { $push: "$details" }, Name: { $first: "$Name" } } }.