ใช้ Positional Operator $ Project เฉพาะ Nested Object ที่ Match
เมื่อมี Array of Objects และต้องการ Return เฉพาะ Object ที่ Match เงื่อนไข ใช้ $ (Positional Projection) ใน Projection Document
ตัวอย่างข้อมูล: คะแนนวิชาต่างๆ ใน Array
> db.queryNestedObject.insertOne({
"StudentName": "James",
"StudentSubjectScore": [
{ "StudentMongoDBScore": 98 },
{ "StudentCScore": 92 },
{ "StudentJavaScore": 91 }
]
});
คิวรี: หา StudentJavaScore = 91 และ Project เฉพาะ Object นั้น
> db.queryNestedObject.find(
{ 'StudentSubjectScore.StudentJavaScore': 91 },
{ 'StudentSubjectScore.$': 1, _id: 0 }
);
ผลลัพธ์
{ "StudentSubjectScore" : [ { "StudentJavaScore" : 91 } ] }
คำอธิบาย
- Query:
StudentSubjectScore.StudentJavaScoreใช้ Dot Notation เข้า Array of Objects - Projection:
StudentSubjectScore.$Return เฉพาะ Element แรกที่ Match _id: 0ซ่อน _id
ข้อจำกัดของ Positional $
- Return Element แรก ที่ Match เท่านั้น
- ใช้ได้ 1 ตัวต่อ Query (ไม่รองรับ Multiple Positional)
- ต้องมี Field Path ใน Query Condition
ทางเลือก: ใช้ $elemMatch ใน Projection (MongoDB 3.2+)
Return ทุก Element ที่ Match (ไม่ใช่แค่ตัวแรก)
db.queryNestedObject.find(
{ "StudentSubjectScore.StudentJavaScore": 91 },
{ StudentSubjectScore: { $elemMatch: { StudentJavaScore: 91 } }, _id: 0 }
);
Aggregation Alternative (ยืดหยุ่นที่สุด)
db.queryNestedObject.aggregate([
{ $match: { "StudentSubjectScore.StudentJavaScore": 91 } },
{ $project: {
StudentName: 1,
StudentSubjectScore: {
$filter: {
input: "$StudentSubjectScore",
cond: { $eq: ["$$this.StudentJavaScore", 91] }
}
}
}}
]);
Use Cases
- Embedded Documents: Orders → Items, Users → Addresses
- Versioned Data: Document → Versions Array
- Category/Tag Systems: Product → Variants Array