Khi cần tìm document mà **một phần tử** trong mảng object thỏa mãn **nhiều điều kiện cùng lúc**, hãy dùng $elemMatch. Nếu chỉ một điều kiện, dot notation thường đủ.
Cú pháp
db.collection.find({
"trườngMảng": { $elemMatch: { "trườngCon1": giáTrị1, "trườngCon2": giáTrị2 } }
}).pretty();
Ví dụ minh họa
Tạo collection objectInAnArrayDemo với mảng StudentDetails chứa các object:
> db.objectInAnArrayDemo.insertOne({
"StudentDetails": [
{ "StudentName": "John", "StudentMessage": "Hi" },
{ "StudentName": "Larry", "StudentMessage": "Hello" }
]
});
> db.objectInAnArrayDemo.insertOne({
"StudentDetails": [
{ "StudentName": "Carol", "StudentMessage": "Hello" },
{ "StudentName": "David", "StudentMessage": "Good Morning" }
]
});
Hiển thị tất cả:
> db.objectInAnArrayDemo.find().pretty();
Kết quả:
{
"_id" : ObjectId("..."),
"StudentDetails" : [
{ "StudentName" : "John", "StudentMessage" : "Hi" },
{ "StudentName" : "Larry", "StudentMessage" : "Hello" }
]
}
{
"_id" : ObjectId("..."),
"StudentDetails" : [
{ "StudentName" : "Carol", "StudentMessage" : "Hello" },
{ "StudentName" : "David", "StudentMessage" : "Good Morning" }
]
}
Tìm document có phần tử StudentMessage = "Good Morning"
> db.objectInAnArrayDemo.find({
"StudentDetails": { $elemMatch: { "StudentMessage": "Good Morning" } }
}).pretty();
Kết quả: Trả về document thứ 2 (chứa David).
{
"_id" : ObjectId("..."),
"StudentDetails" : [
{ "StudentName" : "Carol", "StudentMessage" : "Hello" },
{ "StudentName" : "David", "StudentMessage" : "Good Morning" }
]
}
Tại sao cần $elemMatch?
So sánh 2 truy vấn trên mảng object [{a:1, b:10}, {a:2, b:20}]:
| Truy vấn | Kết quả | Giải thích |
|---|---|---|
{ "arr.a": 1, "arr.b": 20 } | Khớp (True) | Dot notation: a=1 ở phần tử 1, b=20 ở phần tử 2 -> **khớp cross-element** |
{ "arr": { $elemMatch: { a: 1, b: 20 } } } | Không khớp (False) | $elemMatch: Yêu cầu **CÙNG MỘT** phần tử có a=1 VÀ b=20 |
{ "arr": { $elemMatch: { a: 1, b: 10 } } } | Khớp (True) | Phần tử 1 thỏa cả 2 điều kiện |
Khi nào dùng $elemMatch?
- Mảng chứa **object** (không phải giá trị đơn giản).
- Cần khớp **nhiều field** trên **cùng một** element.
- Kết hợp với các toán tử so sánh (
$gt,$lt,$regex...).
Lưu ý
- $elemMatch không thể dùng với mảng giá trị nguyên thủy (string, number) - dùng dot notation hoặc $in/$all.
- Chỉ trả về document cha, không trả về chỉ element khớp (dùng aggregation
$filterhoặc$elemMatchtrong projection để lấy element con).