Để lấy chỉ phần dữ liệu lồng sâu (nested object) thay vì toàn bộ document, dùng findOne() kết hợp projection với $elemMatch.
Dữ liệu mẫu phức tạp
> db.demo109.insertOne({
"Name" : "Chris",
"Subjects" : [
{ "Id" : "100", "Name":"MySQL", "InstructorDetails" : [ { "Name" : "John" } ] },
{ "Id" : "101", "Name":"MongoDB", "InstructorDetails" : [ { "Name" : "Mike" } ] }
]
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2ee7df9fd5fd66da21447a") }
Truy vấn findOne với projection $elemMatch
> db.demo109.findOne(
{ Name: "Chris" },
{ 'Subjects': { $elemMatch: {'Id':"100"} } },
function (err, doc) { console.log(doc) }
);
Kết quả
{ "_id" : ObjectId("5e2ee7df9fd5fd66da21447a"), "Subjects" : [ { "Id" : "100", "Name" : "MySQL", "InstructorDetails" : [ { "Name" : "John" } ] } ] }
Giải thích:
findOne(): Chỉ trả về 1 document đầu tiên khớp- Tham số 2 (projection):
{ 'Subjects': { $elemMatch: {'Id':"100"} } }- Chỉ trả về phần tử đầu tiên trong mảng Subjects có Id="100" - Giữ nguyên cấu trúc lồng nhau của phần tử đó (InstructorDetails vẫn nguyên vẹn)
Lưu ý: $elemMatch trong projection chỉ trả về một phần tử đầu tiên khớp. Nên dùng aggregate với $filter nếu cần nhiều phần tử hoặc biến đổi phức tạp hơn.