Giới thiệu
Để tìm tài liệu dựa trên giá trị trong mảng (tags), bạn có thể dùng toán tử $elemMatch hoặc đơn giản là truy vấn trực tiếp trên trường mảng. MongoDB tự động match nếu bất kỳ phần tử nào trong mảng thỏa mãn điều kiện.
Ví dụ minh họa
1. Tạo collection với mảng Tags
> db.layTheoTags.insertOne({ "Tags": ["Tag-1", "Tag-2", "Tag-3"] });
{ "acknowledged" : true, "insertedId" : ObjectId("5c9eb4d5d628fa4220163b79") }
> db.layTheoTags.insertOne({ "Tags": ["Tag-2", "Tag-4", "Tag-5"] });
{ "acknowledged" : true, "insertedId" : ObjectId("5c9eb4d5d628fa4220163b7a") }
> db.layTheoTags.insertOne({ "Tags": ["Tag-6", "Tag-4", "Tag-3"] });
{ "acknowledged" : true, "insertedId" : ObjectId("5c9eb4d6d628fa4220163b7b") }
2. Cách 1: Truy vấn trực tiếp trên mảng (Đơn giản, khuyên dùng)
> db.layTheoTags.find({ Tags: "Tag-5" }).pretty();
{ "_id" : ObjectId("5c9eb4d5d628fa4220163b7a"), "Tags" : [ "Tag-2", "Tag-4", "Tag-5" ] }
3. Cách 2: Dùng $elemMatch (Khi cần điều kiện phức tạp trên element)
> db.layTheoTags.find({ Tags: { $elemMatch: { $eq: "Tag-2" } } }).pretty();
{ "_id" : ObjectId("5c9eb4d5d628fa4220163b79"), "Tags" : [ "Tag-1", "Tag-2", "Tag-3" ] }
{ "_id" : ObjectId("5c9eb4d5d628fa4220163b7a"), "Tags" : [ "Tag-2", "Tag-4", "Tag-5" ] }
So sánh: Truy vấn trực tiếp vs $elemMatch
| Trường hợp | Cú pháp | Khi nào dùng |
|---|---|---|
| Tìm mảng chứa giá trị đơn giản | { tags: "value" } | Luôn dùng cách này - đơn giản, dùng index |
| Tìm mảng object thỏa nhiều điều kiện | { arr: { $elemMatch: { a: 1, b: 2 } } } | Cần match nhiều field trên CÙNG 1 element |
| Tìm mảng có element > 10 VÀ < 20 | { arr: { $elemMatch: { $gt: 10, $lt: 20 } } } | Điều kiện phức tạp trên element |
Ví dụ $elemMatch thực sự cần thiết (Array of Objects)
// Dữ liệu
{ "sanPham": [ { "ten": "Ao", "gia": 100, "size": "M" }, { "ten": "Quan", "gia": 200, "size": "L" } ] }
// SAI: Tìm sản phẩm tên "Ao" VÀ giá 200 (khác element)
db.collection.find({ "sanPham.ten": "Ao", "sanPham.gia": 200 });
// Trả về doc này (vì có element tên Ao VÀ có element giá 200)
// ĐÚNG: Tìm element CÓ CẢ tên "Ao" VÀ giá 200
db.collection.find({ sanPham: { $elemMatch: { ten: "Ao", gia: 200 } } });
// Không trả về doc trên (vì không có element nào thỏa cả 2)
Các query tags phổ biến khác
// Chứa ít nhất một trong các tag
db.collection.find({ tags: { $in: ["Tag-1", "Tag-2"] } });
// Chứa TẤT CẢ các tag
db.collection.find({ tags: { $all: ["Tag-1", "Tag-2"] } });
// Số lượng tag chính xác
db.collection.find({ tags: { $size: 3 } });
// Kết hợp: Có Tag-1, Tag-2 VÀ đúng 3 tag
db.collection.find({ tags: { $all: ["Tag-1", "Tag-2"], $size: 3 } });
Index cho mảng
MongoDB tự động tạo **Multikey Index** khi index trường mảng:
db.collection.createIndex({ "Tags": 1 });
// Tạo index entry cho TỪNG phần tử trong mảng Tags