Để truy vấn so sánh hai trường trong cùng một document MongoDB, bạn sử dụng toán tử $where với biểu thức JavaScript.
Cú pháp
db.collection.find({
$where: "this.field1 operator this.field2"
})
Ví dụ minh họa
Tạo collection và dữ liệu
> db.queryInSameDocumentsDemo.insertOne({"StudentDetails":{"StudentName":"John"},"NewStudentDetails":{"StudentName":"Carol"}});
{ "acknowledged" : true, "insertedId" : ObjectId("5c90096ed3c9d04998abf017") }
> db.queryInSameDocumentsDemo.insertOne({"StudentDetails":{"StudentName":"Bob"},"NewStudentDetails":{"StudentName":"Bob"}});
{ "acknowledged" : true, "insertedId" : ObjectId("5c900a435705caea966c5573") }
Xem dữ liệu
> db.queryInSameDocumentsDemo.find().pretty();
{
"_id" : ObjectId("5c90096ed3c9d04998abf017"),
"StudentDetails" : { "StudentName" : "John" },
"NewStudentDetails" : { "StudentName" : "Carol" }
}
{
"_id" : ObjectId("5c900a435705caea966c5573"),
"StudentName" : "Bob",
"NewStudentDetails" : { "StudentName" : "Bob" }
}
Trường hợp 1: So sánh bằng (==)
Tìm document có StudentName giống nhau trong cả 2 object lồng nhau:
> db.queryInSameDocumentsDemo.find( {
$where: "this.StudentDetails.StudentName == this.NewStudentDetails.StudentName"
}).pretty();
{
"_id" : ObjectId("5c900a435705caea966c5573"),
"StudentDetails" : { "StudentName" : "Bob" },
"NewStudentDetails" : { "StudentName" : "Bob" }
}
Trường hợp 2: So sánh không bằng (!=)
Tìm document có StudentName khác nhau:
> db.queryInSameDocumentsDemo.find( {
$where: "this.StudentDetails.StudentName != this.NewStudentDetails.StudentName"
}).pretty();
{
"_id" : ObjectId("5c90096ed3c9d04998abf017"),
"StudentDetails" : { "StudentName" : "John" },
"NewStudentDetails" : { "StudentName" : "Carol" }
}
Các phép so sánh hỗ trợ
| Toán tử JS | Ý nghĩa | Ví dụ |
|---|---|---|
== | Bằng (loose equality) | this.a == this.b |
=== | Bằng chặt (strict) | this.a === this.b |
!= | Khác (loose) | this.a != this.b |
!== | Khác chặt | this.a !== this.b |
>, < | Lớn hơn, nhỏ hơn | this.score > this.passingScore |
>=, <= | Lớn/nhỏ hơn hoặc bằng | this.age >= this.minAge |
Thay thế hiệu năng cao hơn: $expr (MongoDB 3.6+)
Thay vì $where (chạy JS engine, chậm), dùng $expr với aggregation operators:
// So sánh bằng
db.queryInSameDocumentsDemo.find({
$expr: { $eq: ["$StudentDetails.StudentName", "$NewStudentDetails.StudentName"] }
});
// So sánh không bằng
db.queryInSameDocumentsDemo.find({
$expr: { $ne: ["$StudentDetails.StudentName", "$NewStudentDetails.StudentName"] }
});
// So sánh số
db.scores.find({
$expr: { $gt: ["$math", "$physics"] }
});
Ưu điểm của $expr
- Không dùng JavaScript engine → nhanh hơn đáng kể
- Có thể dùng index (trong một số trường hợp)
- An toàn hơn (không injection risk)
- Hỗ trợ đầy đủ aggregation operators: $add, $subtract, $concat, $substr...
Cảnh báo:
$where không dùng được index, quét toàn bộ collection. Chỉ dùng khi $expr không đáp ứng được (logic phức tạp, regex custom, function tùy chỉnh).