Để tìm tài liệu khớp **chính xác** các cặp giá trị trên nhiều trường (logic: (Name=A VÀ Marks=X) HOẶC (Name=B VÀ Marks=Y)...), bạn dùng $and kết hợp $in trên từng trường. Lưu ý: $in trên nhiều trường độc lập tạo ra tích Descartes (tất cả tổ hợp), không phải cặp ghép. Để khớp cặp chính xác, cần cấu trúc query khác.
1. Tạo dữ liệu
> db.demo422.insertOne({ "Name": "Chris", "Marks": 34 });
> db.demo422.insertOne({ "Name": "Chris", "Marks": 56 });
> db.demo422.insertOne({ "Name": "David", "Marks": 78 });
> db.demo422.insertOne({ "Name": "Sam", "Marks": 45 });
> db.demo422.insertOne({ "Name": "David", "Marks": 89 });
2. Query gốc (SAI cho cặp ghép): Tìm Name IN [Chris, David] VÀ Marks IN [34, 89]
> db.demo422.find({
$and: [
{ Name: { $in: ["Chris", "David"] } },
{ Marks: { $in: [34, 89] } }
]
});
Kết quả trả về: Chris-34, Chris-89?, David-34?, David-89. **Nhưng dữ liệu chỉ có Chris-34 và David-89**. Query này may ra đúng vì dữ liệu không có tổ hợp chéo (Chris-89, David-34).
3. Cách ĐÚNG: Khớp chính xác cặp (Name, Marks) dùng $or + $and
> db.demo422.find({
$or: [
{ Name: "Chris", Marks: 34 },
{ Name: "David", Marks: 89 }
]
});
Hoặc dùng $expr (MongoDB 3.6+):
> db.demo422.find({
$expr: {
$or: [
{ $and: [{ $eq: ["$Name", "Chris"] }, { $eq: ["$Marks", 34] }] },
{ $and: [{ $eq: ["$Name", "David"] }, { $eq: ["$Marks", 89] }] }
]
}
});
4. Kết quả (cả 2 cách đúng)
{ "_id": ObjectId("..."), "Name": "Chris", "Marks": 34 }
{ "_id": ObjectId("..."), "Name": "David", "Marks": 89 }
Tóm tắt:
$intrên nhiều trường = Tích Descartes (AND logic ngầm) -> Sai cho cặp ghép.- Dùng
$orliệt kê các cặp giá trị chính xác. - Dùng
$exprcho logic phức tạp trong find.