Toán tử $where cho phép chạy JavaScript expression tùy ý để so sánh nhiều trường hoặc tính toán phức tạp. Cảnh báo: Chậm, không dùng index, nguy hiểm injection nếu input từ user.
Dữ liệu mẫu
> db.demo223.insertOne({"Scores":[56,78]});
{ "acknowledged" : true, "insertedId" : ObjectId("5e3ee4ca03d395bdc2134730") }
> db.demo223.insertOne({"Scores":[88,45]});
{ "acknowledged" : true, "insertedId" : ObjectId("5e3ee4d103d395bdc2134731") }
> db.demo223.insertOne({"Scores":[98,79]});
{ "acknowledged" : true, "insertedId" : ObjectId("5e3ee4d803d395bdc2134732") }
Truy vấn $where
Tìm document có Scores[0] > Scores[1]:
> db.demo223.find({ $where : "this.Scores[0] > this.Scores[1]" });
Kết quả
{ "_id" : ObjectId("5e3ee4d103d395bdc2134731"), "Scores" : [ 88, 45 ] }
{ "_id" : ObjectId("5e3ee4d803d395bdc2134732"), "Scores" : [ 98, 79 ] }
Giải thích:
thistham chiếu đến document hiện tạithis.Scores[0]truy cập phần tử đầu mảng- JavaScript engine đánh giá expression cho mỗi document
⚠️ Hạn chế nghiêm trọng:
- Không sử dụng index → full collection scan
- Chậm hơn nhiều so với query operator chuẩn
- Rủi ro bảo mật nếu nối chuỗi input user
- Không hoạt động trong sharded cluster một số trường hợp
Thay thế hiện đại (MongoDB 3.6+): Dùng $expr với aggregation operators:
db.demo223.find({ $expr: { $gt: [ { $arrayElemAt: ["$Scores", 0] }, { $arrayElemAt: ["$Scores", 1] } ] } });
Cách này dùng index, an toàn, nhanh hơn.