Longueur du champ de la chaîne en mongoDB
le type de données du champ est String. J'aimerais récupérer les données lorsque la longueur des caractères du nom du champ est supérieure à 40.
j'ai essayé ces requêtes mais en retournant l'erreur. 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
}
cela fonctionne en 2.4.9 mais ma version est 2.6.5
3 réponses
Pour MongoDB 3.6 et versions ultérieures:
$expr
l'opérateur permet l'utilisation d'expressions d'agrégation dans le langage de requête, donc vous pouvez tirer parti de l'utilisation de $strLenCP
opérateur de vérifier la longueur de la chaîne comme suit:
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] }
})
pour MongoDB 3.4 et les versions plus récentes:
vous pouvez également utiliser le cadre d'agrégation $redact
opérateur de pipeline qui vous permet de traiter la condition logique avec le $cond
opérateur et utilise les opérations spéciales $$KEEP
pour "garder" le document dans le cas où la condition logique est vraie ou $$PRUNE
pour "supprimer" le document où la condition était fausse.
cette opération est similaire à avoir une $project
pipeline qui sélectionne les champs de la collection et crée un nouveau champ qui contient le résultat de la requête de condition logique et ensuite un$match
sauf que $redact
utilise un seul étage de pipeline qui est plus efficace.
quant à la condition logique, il y a Opérateurs D'Agrégation De Chaînes De Caractères que vous pouvez utiliser $strLenCP
opérateur de vérifier la longueur de la chaîne. Si la longueur est $gt
à une valeur spécifiée, alors c'est un vrai match et que le document est "conservé". Sinon, il est "taillé" et s'en débarrasser.
envisagez d'exécuter l'opération d'ensemble suivante qui démontre le concept ci-dessus:
db.usercollection.aggregate([
{ "$match": { "name": { "$exists": true } } },
{
"$redact": {
"$cond": [
{ "$gt": [ { "$strLenCP": "$name" }, 40] },
"$$KEEP",
"$$PRUNE"
]
}
},
{ "$limit": 2 }
])
Si vous utilisez $where
, essayez de votre requête sans l'enfermer entre parenthèses:
db.usercollection.find({$where: "this.name.length > 40"}).limit(2);
une meilleure requête serait de vérifier l'existence du champ et ensuite de vérifier la longueur:
db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2);
ou:
db.usercollection.find({name: {$exists: true}, $where: "this.name.length >
40"}).limit(2);
MongoDB évalue non -$where
les opérations de requête avant $where
expressions et non$where
les énoncés de requête peuvent utiliser un index. Une bien meilleure performance est de stocker la longueur de la chaîne un autre champ et ensuite vous pouvez indexer ou rechercher; appliquer $where
sera beaucoup plus lent par rapport à cela. Il est recommandé d'utiliser les expressions JavaScript et le $where
opérateur en dernier recours lorsque vous ne pouvez pas structurer les données d'une autre manière, ou lorsque vous avez affaire à un
petit sous-ensemble de données.
une approche différente et plus rapide qui évite l'utilisation de $where
opérateur $regex
opérateur. Considérez le schéma suivant qui recherche
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
Remarque: - la docs:
si un index existe pour le champ, alors MongoDB correspond à la normale expression par rapport aux valeurs de l'indice, qui peuvent être plus rapides que balayage de la collection. D'autres optimisations peuvent se produire si la régulière expression est une "expression préfixe", ce qui signifie que tout le potentiel les matchs commencent avec la même chaîne. Cela permet à MongoDB de construire un "range" à partir de ce préfixe et ne correspondent qu'à ces valeurs de la indice qui se situent dans cette fourchette.
une expression régulière est une "expression de préfixe" si elle commence par un caret
(^)
ou un ancrage à gauche(\A)
, suivie d'une chaîne de simples symbole. Par exemple, l'expression régulière/^abc.*/
sera optimisé par la correspondant seulement à l'encontre des valeurs de l'indice commençant parabc
.en Outre, alors que
/^a/, /^a.*/,
et/^a.*$/
équivalent match les cordes, elles ont des caractéristiques de performance différentes. L'ensemble de ces expressions l'utilisation d'un index si un index approprié existe; cependant,/^a.*/
et/^a.*$/
sont plus lents./^a/
peut arrêter de scanner après correspondant au préfixe.
j'ai eu un scénario similaire, mais dans mon cas la chaîne de caractères n'est pas un attribut de premier niveau. C'est à l'intérieur d'un objet. Ici je ne pouvais pas trouver une réponse convenable. Alors j'ai pensé partager ma solution avec vous tous(espérons que cela aidera n'importe qui avec un type similaire de problème).
Parent Collection
{
"Child":
{
"name":"Random Name",
"Age:"09"
}
}
Ex: si nous avons besoin d'obtenir seulement des collections que la longueur du nom de l'enfant est supérieure à 10 caractères.
db.getCollection('Parent').find({$where: function() {
for (var field in this.Child.name) {
if (this.Child.name.length > 10)
return true;
}
}})
une mise à jour sur Mongo 4.0, il devient plus facile et plus fluide:
find({name: { $gt: 40 }}, function(err, posts){
res.render('blog', {posts:posts}); // your code here
});