Đối với MongoDB 3.6 và mới hơn:
$expr
toán tử cho phép sử dụng các biểu thức tổng hợp trong ngôn ngữ truy vấn, do đó bạn có thể tận dụng việc sử dụng $strLenCP
toán tử để kiểm tra độ dài của chuỗi như sau:
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] }
})
Đối với MongoDB 3.4 và mới hơn:
Bạn cũng có thể sử dụng khung tổng hợp với $redact
toán tử đường ống cho phép bạn xử lý điều kiện logic với $cond
và sử dụng các phép toán đặc biệt $$KEEP
để "giữ" tài liệu có điều kiện logic đúng hoặc $$PRUNE
để "xóa" tài liệu có điều kiện sai.
Thao tác này tương tự như có một $project
đường ống chọn các trường trong bộ sưu tập và tạo một trường mới chứa kết quả từ truy vấn điều kiện logic và sau đó là $match
tiếp theo , ngoại trừ $redact
sử dụng một giai đoạn đường ống duy nhất hiệu quả hơn.
Đối với điều kiện logic, có các toán tử tổng hợp chuỗi mà bạn có thể sử dụng $strLenCP
toán tử để kiểm tra độ dài của chuỗi. Nếu độ dài là $gt
một giá trị được chỉ định thì đây là giá trị khớp đúng và tài liệu được "lưu giữ". Nếu không, nó sẽ bị "cắt bớt" và bị loại bỏ.
Hãy xem xét chạy hoạt động tổng hợp sau đây để thể hiện khái niệm trên:
db.usercollection.aggregate([
{ "$match": { "name": { "$exists": true } } },
{
"$redact": {
"$cond": [
{ "$gt": [ { "$strLenCP": "$name" }, 40] },
"$$KEEP",
"$$PRUNE"
]
}
},
{ "$limit": 2 }
])
Nếu sử dụng $where
, hãy thử truy vấn của bạn mà không có dấu ngoặc kèm theo:
db.usercollection.find({$where: "this.name.length > 40"}).limit(2);
Một truy vấn tốt hơn sẽ là kiểm tra sự tồn tại của trường và sau đó kiểm tra độ dài:
db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2);
hoặc:
db.usercollection.find({name: {$exists: true}, $where: "this.name.length >
40"}).limit(2);
MongoDB đánh giá không phải là $where
các thao tác truy vấn trước $where
biểu thức và không phải $where
câu lệnh truy vấn có thể sử dụng một chỉ mục. Một hiệu suất tốt hơn nhiều là lưu trữ độ dài của chuỗi dưới dạng một trường khác và sau đó bạn có thể lập chỉ mục hoặc tìm kiếm trên đó; áp dụng $where
sẽ chậm hơn nhiều so với điều đó. Bạn nên sử dụng các biểu thức JavaScript và $where
là phương án cuối cùng khi bạn không thể cấu trúc dữ liệu theo bất kỳ cách nào khác hoặc khi bạn đang xử lý tập hợp con dữ liệu nhỏ.
Một cách tiếp cận khác và nhanh hơn tránh sử dụng $where
toán tử là $regex
nhà điều hành. Hãy xem xét mẫu tìm kiếm sau đây
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
Lưu ý - Từ tài liệu :
Nếu tồn tại một chỉ mục cho trường, thì MongoDB sẽ đối sánh biểu thức chính quy với các giá trị trong chỉ mục, có thể nhanh hơn quét acollection. Tối ưu hóa hơn nữa có thể xảy ra nếu biểu thức chính quy là một "biểu thức tiền tố", có nghĩa là tất cả các đối sánh tiềm năng bắt đầu bằng cùng một chuỗi. Điều này cho phép MongoDB tạo một "phạm vi" từ tiền tố đó và chỉ khớp với các giá trị từ chỉ mục nằm trong phạm vi đó.
Một biểu thức chính quy là một “biểu thức tiền tố” nếu nó bắt đầu bằng acaret
(^)
hoặc một ký tự neo bên trái(\A)
, theo sau là một chuỗi các ký hiệu đơn giản. Ví dụ:regex/^abc.*/
sẽ chỉ được tối ưu hóa bằng cách so khớp với các giá trị từ chỉ mục bắt đầu bằngabc
.Ngoài ra, while
/^a/, /^a.*/,
và/^a.*$/
khớp các chuỗi tương đương, chúng có các đặc điểm hiệu suất khác nhau. Tất cả các biểu thức này sử dụng một chỉ mục nếu một chỉ mục thích hợp tồn tại; tuy nhiên,/^a.*/
và/^a.*$/
chậm hơn./^a/
có thể ngừng quét sau khi đối sánh tiền tố.