Pour MongoDB 3.6 et versions ultérieures :
Le $expr
L'opérateur permet l'utilisation d'expressions d'agrégation dans le langage de requête, vous pouvez donc tirer parti de l'utilisation de $strLenCP
pour 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 versions ultérieures :
Vous pouvez également utiliser le cadre d'agrégation avec le $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 "conserver" le document où la condition logique est vraie ou $$PRUNE
pour "supprimer" le document où la condition était fausse.
Cette opération est similaire à un $project
pipeline qui sélectionne les champs de la collection et crée un nouveau champ contenant le résultat de la requête de condition logique, puis un $match
suivant , sauf que $redact
utilise une seule étape de pipeline qui est plus efficace.
En ce qui concerne la condition logique, il existe des opérateurs d'agrégation de chaînes que vous pouvez utiliser $strLenCP
opérateur pour vérifier la longueur de la chaîne. Si la longueur est $gt
une valeur spécifiée, il s'agit d'une correspondance vraie et le document est "conservé". Sinon, il est "élagué" et jeté.
Envisagez d'exécuter l'opération d'agrégation suivante qui illustre 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 votre requête sans les crochets :
db.usercollection.find({$where: "this.name.length > 40"}).limit(2);
Une meilleure requête serait de vérifier l'existence du champ, puis 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
opérations de requête avant $where
expressions et non-$where
les instructions de requête peuvent utiliser un index. Une bien meilleure performance consiste à stocker la longueur de la chaîne dans un autre champ, puis vous pouvez l'indexer ou la rechercher ; appliquer $where
sera beaucoup plus lent par rapport à cela. Il est recommandé d'utiliser des 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 traitez un petit sous-ensemble de données.
Une approche différente et plus rapide qui évite l'utilisation du $where
l'opérateur est le $regex
opérateur. Considérez le modèle suivant qui recherche
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
Remarque - À partir de la documentation :
Si un index existe pour le champ, MongoDB fait correspondre l'expression régulière aux valeurs de l'index, ce qui peut être plus rapide qu'une analyse de collection. Une optimisation supplémentaire peut se produire si l'expression régulière est une « expression de préfixe », ce qui signifie que toutes les correspondances potentielles commencent par la même chaîne. Cela permet à MongoDB de construire une "plage" à partir de ce préfixe et de ne faire correspondre que les valeurs de l'index qui se situent dans cette plage.
Une expression régulière est une "expression de préfixe" si elle commence par un accentuation
(^)
ou une ancre gauche(\A)
, suivi d'une chaîne de symboles simples. Par exemple, la regex/^abc.*/
sera optimisé en comparant uniquement les valeurs de l'index qui commencent parabc
.De plus, tandis que
/^a/, /^a.*/,
et/^a.*$/
correspondent à des chaînes équivalentes, elles ont des caractéristiques de performance différentes. Toutes ces expressions utilisent un index si un index approprié existe; cependant,/^a.*/
, et/^a.*$/
sont plus lents./^a/
peut arrêter l'analyse après la correspondance du préfixe.