MongoDB shell cho phép dùng JavaScript expression trong find() để thực hiện ép kiểu (cast) ngầm định khi so sánh.
Cú pháp
db.collection.find("this.trường > giáTrị");
Trong chuỗi query, this tham chiếu đến document hiện tại. JavaScript sẽ tự chuyển đổi kiểu khi so sánh.
Ví dụ minh họa
Tạo collection castingDemo với field Amount lưu dưới dạng **String**:
> db.castingDemo.insertOne({ "Amount": "200" });
> db.castingDemo.insertOne({ "Amount": "100" });
> db.castingDemo.insertOne({ "Amount": "110" });
> db.castingDemo.insertOne({ "Amount": "95" });
> db.castingDemo.insertOne({ "Amount": "85" });
> db.castingDemo.insertOne({ "Amount": "75" });
Hiển thị:
> db.castingDemo.find().pretty();
Kết quả:
{ "_id" : ..., "Amount" : "200" }
{ "_id" : ..., "Amount" : "100" }
{ "_id" : ..., "Amount" : "110" }
{ "_id" : ..., "Amount" : "95" }
{ "_id" : ..., "Amount" : "85" }
{ "_id" : ..., "Amount" : "75" }
Truy vấn: Amount > 85 (tự ép string sang number)
> db.castingDemo.find("this.Amount > 85");
Kết quả: Các document có Amount = "200", "100", "110", "95".
{ "_id" : ..., "Amount" : "200" }
{ "_id" : ..., "Amount" : "100" }
{ "_id" : ..., "Amount" : "110" }
{ "_id" : ..., "Amount" : "95" }
Cách hiện đại & khuyên dùng: $expr (Aggregation trong find)
Từ MongoDB 3.6, dùng $expr với các toán tử aggregation ($gt, $toInt, $toDouble...) rõ ràng và an toàn hơn:
// Ép kiểu tường minh với $toInt
db.castingDemo.find({ $expr: { $gt: [ { $toInt: "$Amount" }, 85 ] } });
// Hoặc $convert (MongoDB 4.0+) với xử lý lỗi
db.castingDemo.find({ $expr: { $gt: [ { $convert: { input: "$Amount", to: "int", onError: 0 } }, 85 ] } });
So sánh 2 cách
| Đặc điểm | find("this...") | find({ $expr: ... }) |
|---|---|---|
| Cú pháp | JavaScript string | Aggregation expression (object) |
| Ép kiểu | Ngầm định (JS type coercion) | Tường minh ($toInt, $toDouble...) |
| Sử dụng Index | **Không thể** dùng index | **Không thể** dùng index (cần $expr) |
| An toàn | Rủi ro injection, lỗi type lạ | An toàn, chuẩn MongoDB |
| Hỗ trợ | Legacy shell | MongoDB 3.6+ (khuyên dùng) |
Lưu ý
- Cả 2 cách **không sử dụng index** trên field
Amountvì phải tính toán trên mỗi document. - Giải pháp tối ưu: **Chuẩn hóa dữ liệu** (store as Number) hoặc dùng **Schema Validation** ép kiểu khi insert.
- Trong driver (Node.js, Python...): Không dùng được
"this...". Phải dùng$exprhoặc xử lý ở application layer.