Длина значения строкового поля в mongoDB
тип данных поля-String. Я хотел бы получить данные, где длина символа имени поля больше 40.
Я пробовал эти запросы, но возвращается ошибка. 1.
db.usercollection.find(
{$where: "(this.name.length > 40)"}
).limit(2);
output :error: {
"$err" : "TypeError: Cannot read property 'length' of undefined near '40)' ",
"code" : 16722
}
это работает в 2.4.9 но моя версия 2.6.5
3 ответов
для MongoDB 3.6 и новее:
на $expr
оператор позволяет использовать выражения агрегации в языке запросов, таким образом, вы можете использовать использовать $strLenCP
оператор для проверки длины строки следующим образом:
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] }
})
для MongoDB 3.4 и новее:
вы также можете использовать структуру агрегации с $redact
оператор конвейера, который позволяет обрабатывать логическое условие с помощью $cond
оператор и использует специальные операции $$KEEP
"сохранить" документ, где логическое условие true или $$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);
Примечание - С docs:
если для поля существует индекс, то MongoDB соответствует регулярному выражение против значений в индексе, которые могут быть быстрее сканирование коллекции. Дальнейшая оптимизация может произойти если регулярно выражение является "префиксным выражением", что означает, что все потенциальные совпадения начинаются с одной строки. Это позволяет MongoDB построить "диапазон" от этого префикса и только соответствует этим значениям из индекс, который попадает в этот диапазон.
регулярное выражение является "префиксным выражением", если оно начинается с caret
(^)
или левый якорь(\A)
, за которым следует строка простых атрибутика. Например, regex/^abc.*/
будет оптимизирован сопоставление только со значениями из индекса, которые начинаются сabc
.дополнительно, в то время как
/^a/, /^a.*/,
и/^a.*$/
матч эквивалент струны, они имеют разные эксплуатационные характеристики. Все это выражения используют индекс, если соответствующий индекс существует; однако,/^a.*/
и/^a.*$/
медленнее./^a/
может остановить сканирование после соответствует префиксу.
у меня был похожий сценарий, но в моем случае строка не 1-го атрибута уровня. Он находится внутри объекта. Здесь я не мог найти подходящего ответа. Поэтому я решил поделиться своим решением со всеми вами(надеюсь, это поможет кто-нибудь с подобной проблемой).
Parent Collection
{
"Child":
{
"name":"Random Name",
"Age:"09"
}
}
Ex: если нам нужно получить только коллекции, длина имени ребенка которых превышает 10 символов.
db.getCollection('Parent').find({$where: function() {
for (var field in this.Child.name) {
if (this.Child.name.length > 10)
return true;
}
}})
обновление на Mongo 4.0, становится проще и более свободно:
find({name: { $gt: 40 }}, function(err, posts){
res.render('blog', {posts:posts}); // your code here
});