ใช้ Positional $ Operator กับ Dot Notation
เมื่อต้องการอัปเดตอิลิเมนต์เฉพาะในอาร์เรย์ของออบเจ็กต์ ใช้ query match ฟิลด์ในอิลิเมนต์ แล้วอัปเดตด้วย $ (positional operator)
ตัวอย่างข้อมูล
> db.demo489.insertOne({
details: [
{ id: 101, Info1: { StudentName: "Chris" }, Info2: { TeacherName: "David" } },
{ id: 102, Info1: { StudentName: "Carol" }, Info2: { TeacherName: "Mike" } }
]
});
Query อัปเดตอิลิเมนต์ id=102
> db.demo489.update(
{ "details.id": 102 },
{ $set: {
"details.$.Info1.StudentName": "Robert",
"details.$.Info2.TeacherName": "John",
"details.$.CountryName": "US"
}}
);
WriteResult({ "nMatched": 1, "nUpserted": 0, "nModified": 1 })
ผลลัพธ์
{ "_id": ObjectId(...), "details": [
{ "id": 101, "Info1": { "StudentName": "Chris" }, "Info2": { "TeacherName": "David" } },
{ "id": 102, "Info1": { "StudentName": "Robert" }, "Info2": { "TeacherName": "John" }, "CountryName": "US" }
] }
คำอธิบาย
{ "details.id": 102 }- หาเอกสารที่มีอิลิเมนต์ใน details.id = 102details.$- อ้างอิง **อิลิเมนต์แรกที่ match** ในอาร์เรย์ details- อัปเดตฟิลด์ซ้อน:
Info1.StudentName,Info2.TeacherName - เพิ่มฟิลด์ใหม่:
CountryNameในอิลิเมนต์เดียวกัน
ข้อจำกัดของ Positional $
- อัปเดตได้ **อิลิเมนต์แรกที่ match** เท่านั้น
- ไม่รองรับ nested array (อาร์เรย์ในอาร์เรย์)
- query ต้อง match ฟิลด์ในอิลิเมนต์เดียวกับที่จะอัปเดต
ทางเลือก: ArrayFilters (MongoDB 3.6+)
db.demo489.updateOne(
{ "details.id": 102 },
{ $set: { "details.$[elem].Info1.StudentName": "Robert" } },
{ arrayFilters: [{ "elem.id": 102 }] }
);
// อัปเดตทุกอิลิเมนต์ที่ match
db.demo489.updateMany(
{},
{ $set: { "details.$[elem].Status": "Active" } },
{ arrayFilters: [{ "elem.id": { $gte: 100 } }] }
);
รูปแบบใหม่แนะนำ
// ใช้ updateOne/updateMany แทน update()
db.demo489.updateOne(
{ "details.id": 102 },
{ $set: { "details.$.Info1.StudentName": "Robert" } }
);