Đối với MongoDB 3.6 và mới hơn:
Nhà điều hành $expr
cho phép việc sử dụng các tập hợp biểu thức trong ngôn ngữ truy vấn, do đó bạn có thể tận dụng việc sử dụng toán tử $strLenCP
để 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 khuôn khổ hợp với các nhà điều hành $redact
đường ống cho phép bạn proccess điều kiện hợp lý với các nhà điều hành $cond
và sử dụng các hoạt động đặc biệt $$KEEP
để "giữ" tài liệu ở nơi điều kiện logic là đúng hoặc $$PRUNE
để "xóa" tài liệu trong đó điều kiện sai.
Thao tác này cũng tương tự như việc có một đường ống $project
mà lựa chọn các trường trong việc thu thập và tạo ra một lĩnh vực mới chứa kết quả từ truy vấn tình trạng hợp lý và sau đó một tiếp theo $match
, ngoại trừ việc $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ó String Aggregation Operators bạn có thể sử dụng toán tử $strLenCP
để kiểm tra độ dài của chuỗi. Nếu độ dài là $gt
giá trị được chỉ định, thì đây là giá trị phù hợp và tài liệu được "lưu giữ". Nếu không, nó được "cắt xén" và bị loại bỏ.
xem xét việc chạy các hoạt động tổng hợp sau đó chứng minh 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 không có dấu ngoặc kèm theo:
db.usercollection.find({$where: "this.name.length > 40"}).limit(2);
Một tốt hơn truy vấn sẽ là để kiểm tra sự tồn tại của trường và sau đó kiểm tra lengt h:
db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2);
hay:
db.usercollection.find({name: {$exists: true}, $where: "this.name.length >
40"}).limit(2);
MongoDB đánh giá các hoạt động phi $where
truy vấn trước khi $where
biểu thức và phi $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 như 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 biểu thức JavaScript và toán tử $where
làm phương sách 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ý một tập hợp con dữ liệu nhỏ .
Một cách tiếp cận khác nhau và nhanh hơn mà tránh được việc sử dụng các nhà điều hành $where
là các nhà điều hành $regex
. Hãy xem xét các mô hình sau đó tìm kiếm
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
Note - Từ docs:
Nếu một chỉ số tồn tại cho lĩnh vực này, sau đó MongoDB phù hợp với biểu thức chính quy đối với các giá trị trong chỉ mục, có thể nhanh hơn so với quét bộ sưu tập . Tối ưu hóa thêm có thể xảy ra nếu biểu thức thông thường là "biểu thức tiền tố", có nghĩa là tất cả các đối sánh có thể là bắt đầu bằng cùng một chuỗi. Điều này cho phép MongoDB xây dựng 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 hiện tiền tố” nếu nó bắt đầu với một caret (^)
hoặc neo trái (\A)
, tiếp theo là một chuỗi các ký tự đơn giản. Ví dụ: regex /^abc.*/
sẽ được tối ưu hóa bởi chỉ khớp với các giá trị từ chỉ mục bắt đầu bằng abc
.
Ngoài ra, trong khi /^a/, /^a.*/,
và /^a.*$/
khớp tương đương với chuỗi, chúng 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 chỉ mục nếu 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 khớp với tiền tố.
Bạn đã thử gt thay vì> – gpullen