เมื่อต้องการค้นหาเอกสารที่ array field มี element ตรงกับหลายเงื่อนไขพร้อมกัน ให้ใช้ $elemMatch ซึ่งจะจับคู่ element เดียวที่ตรงทุกเงื่อนไข
สร้างคอลเลกชันและข้อมูลตัวอย่าง
> db.demo87.insertOne({
id:101,
"Details": [
{ "EmployeeName": "Chris", "Salary": 45000 },
{ "EmployeeName": "David", "Salary": 50000 }
]
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2c113871bf0181ecc422ab") }
> db.demo87.insertOne({
id:102,
"Details": [
{ "EmployeeName": "Chris", "Salary": 65000 },
{ "EmployeeName": "Mike", "Salary": 100000 }
]
});
{ "acknowledged" : true, "insertedId" : ObjectId("5e2c114371bf0181ecc422ac") }
แสดงข้อมูลทั้งหมด
> db.demo87.find();
ผลลัพธ์: 2 เอกสาร ทั้งคู่มี Chris ใน Details แต่ Salary ต่างกัน
Query กรองด้วย $elemMatch หลายเงื่อนไข
> db.demo87.find({ Details: { $elemMatch: { "EmployeeName": 'Chris', "Salary": 65000 }}});
ผลลัพธ์
{ "_id" : ObjectId("5e2c114371bf0181ecc422ac"), "id" : 102, "Details" : [
{ "EmployeeName" : "Chris", "Salary" : 65000 },
{ "EmployeeName" : "Mike", "Salary" : 100000 }
] }
คำอธิบาย:
- เอกสาร id=101: มี Chris แต่ Salary=45000 → ไม่ตรง
- เอกสาร id=102: มี Chris และ Salary=65000 ใน element เดียวกัน → ตรง
ความแตกต่าง: $elemMatch vs Query ธรรมดา
Query ธรรมดา (ผิดสำหรับกรณีนี้):
db.demo87.find({ "Details.EmployeeName": "Chris", "Details.Salary": 65000 })
จะคืนค่า ทั้งสองเอกสาร เพราะ MongoDB match EmployeeName จาก element ตัวแรก และ Salary จาก element ตัวที่สอง (cross-match)
$elemMatch (ถูกต้อง): ต้องเป็น element เดียวกันที่ตรงทั้งสอง field
ใช้ $elemMatch ใน Projection
คืนค่าเฉพาะ element ที่ match:
db.demo87.find(
{ Details: { $elemMatch: { "EmployeeName": 'Chris', "Salary": 65000 }}},
{ Details: { $elemMatch: { "EmployeeName": 'Chris', "Salary": 65000 }} }
)
กรณีเงื่อนไขซับซ้อนมากขึ้น
db.demo87.find({
Details: {
$elemMatch: {
EmployeeName: "Chris",
Salary: { $gte: 60000, $lte: 70000 }
}
}
})
สรุป: ใช้ $elmMatch เสมอเมื่อ query array of objects หลาย field พร้อมกัน เพื่อความถูกต้อง