За MongoDB 3.6 и по-нови:
$expr
оператор позволява използването на изрази за агрегиране в рамките на езика на заявките, като по този начин можете да използвате използването на $strLenCP
оператор, за да проверите дължината на низа, както следва:
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] }
})
За MongoDB 3.4 и по-нови:
Можете също да използвате рамката за агрегиране с $redact
оператор на конвейера, който ви позволява да обработвате логическото условие с $cond
оператор и използва специалните операции $$KEEP
за да "запазите" документа, където логическото условие е вярно или $$PRUNE
за да "премахнете" документа, където условието е било невярно.
Тази операция е подобна на това да имате $project
конвейер, който избира полетата в колекцията и създава ново поле, което съдържа резултата от заявката за логическо условие и след това последващо $match
, с изключение на това $redact
използва един етап на тръбопровода, който е по-ефективен.
Що се отнася до логическото условие, има оператори за агрегиране на низове, които можете да използвате $strLenCP
оператор за проверка на дължината на низа. Ако дължината е $gt
определена стойност, тогава това е вярно съвпадение и документът се "запазва". В противен случай се „подрязва“ и се изхвърля.
Помислете за изпълнение на следната обобщена операция, която демонстрира горната концепция:
db.usercollection.aggregate([
{ "$match": { "name": { "$exists": true } } },
{
"$redact": {
"$cond": [
{ "$gt": [ { "$strLenCP": "$name" }, 40] },
"$$KEEP",
"$$PRUNE"
]
}
},
{ "$limit": 2 }
])
Ако използвате $where
, опитайте заявката си без ограждащите скоби:
db.usercollection.find({$where: "this.name.length > 40"}).limit(2);
По-добра заявка би била да проверите за съществуването на полето и след това да проверите дължината:
db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2);
или:
db.usercollection.find({name: {$exists: true}, $where: "this.name.length >
40"}).limit(2);
MongoDB оценява не-$where
операции на заявка преди $where
изрази и не-$where
заявките могат да използват индекс. Много по-добра производителност е да съхраните дължината на низа като друго поле и след това можете да индексирате или търсите в него; прилагане на $where
ще бъде много по-бавно в сравнение с това. Препоръчително е да използвате JavaScript изрази и $where
оператор като последна мярка, когато не можете да структурирате данните по друг начин или когато работите с малко подмножество от данни.
Различен и по-бърз подход, който избягва използването на $where
операторът е $regex
оператор. Помислете за следния модел, който търси
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
Забележка - От документита :
Ако за полето съществува индекс, тогава MongoDB съпоставя регулярния израз със стойностите в индекса, което може да бъде по-бързо от сканирането на колекция. По-нататъшна оптимизация може да възникне, ако регулярният израз е „префиксен израз“, което означава, че всички потенциални съвпадения започват с един и същ низ. Това позволява на MongoDB да конструира „диапазон“ от този префикс и да съвпада само с онези стойности от индекса, които попадат в този диапазон.
Регулярният израз е „префиксен израз“, ако започва с acaret
(^)
или лява котва(\A)
, последвано от низ от прости символи. Например регулярният израз/^abc.*/
ще бъде оптимизирано чрез съпоставяне само със стойностите от индекса, които започват сabc
.Освен това, докато
/^a/, /^a.*/,
и/^a.*$/
съвпадат с еквивалентни низове, те имат различни характеристики на изпълнение. Всички тези изрази използват индекс, ако съществува подходящ индекс; обаче,/^a.*/
и/^a.*$/
са по-бавни./^a/
може да спре сканирането след съвпадение на префикса.