Para MongoDB 3.6 y posteriores:
El $expr
El operador permite el uso de expresiones de agregación dentro del lenguaje de consulta, por lo que puede aprovechar el uso de $strLenCP
operador para verificar la longitud de la cadena de la siguiente manera:
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] }
})
Para MongoDB 3.4 y posteriores:
También puede usar el marco de agregación con $redact
operador de canalización que le permite procesar la condición lógica con $cond
operador y usa las operaciones especiales $$KEEP
para "mantener" el documento donde la condición lógica es verdadera o $$PRUNE
para "eliminar" el documento donde la condición era falsa.
Esta operación es similar a tener un $project
canalización que selecciona los campos en la colección y crea un nuevo campo que contiene el resultado de la consulta de condición lógica y luego un $match
subsiguiente , excepto que $redact
utiliza una sola etapa de canalización que es más eficiente.
En cuanto a la condición lógica, hay operadores de agregación de cadenas que puede usar $strLenCP
operador para comprobar la longitud de la cadena. Si la longitud es $gt
un valor especificado, entonces esta es una coincidencia verdadera y el documento se "conserva". De lo contrario, se "poda" y se desecha.
Considere ejecutar la siguiente operación agregada que demuestra el concepto anterior:
db.usercollection.aggregate([
{ "$match": { "name": { "$exists": true } } },
{
"$redact": {
"$cond": [
{ "$gt": [ { "$strLenCP": "$name" }, 40] },
"$$KEEP",
"$$PRUNE"
]
}
},
{ "$limit": 2 }
])
Si usa $where
, intente su consulta sin los corchetes adjuntos:
db.usercollection.find({$where: "this.name.length > 40"}).limit(2);
Una mejor consulta sería verificar la existencia del campo y luego verificar la longitud:
db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2);
o:
db.usercollection.find({name: {$exists: true}, $where: "this.name.length >
40"}).limit(2);
MongoDB evalúa no $where
operaciones de consulta antes de $where
expresiones y no $where
las declaraciones de consulta pueden usar un índice. Un rendimiento mucho mejor es almacenar la longitud de la cadena como otro campo y luego puede indexarlo o buscarlo; aplicando $where
será mucho más lento en comparación con eso. Se recomienda utilizar expresiones JavaScript y $where
operador como último recurso cuando no puede estructurar los datos de otra manera, o cuando se trata de un pequeño subconjunto de datos.
Un enfoque diferente y más rápido que evita el uso de $where
el operador es el $regex
operador. Considere el siguiente patrón que busca
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
Nota - De los documentos :
Si existe un índice para el campo, entonces MongoDB compara la expresión regular con los valores del índice, lo que puede ser más rápido que un escaneo de colección. Puede ocurrir una mayor optimización si la expresión regular es una "expresión de prefijo", lo que significa que todas las coincidencias potenciales comienzan con la misma cadena. Esto permite que MongoDB construya un "rango" a partir de ese prefijo y solo coincida con los valores del índice que se encuentran dentro de ese rango.
Una expresión regular es una "expresión de prefijo" si comienza con acaret (^)
o un ancla izquierda (\A)
, seguido de una cadena de símbolos simples. Por ejemplo, la expresión regular /^abc.*/
se optimizará haciendo coincidir solo con los valores del índice que comienzan con abc
.
Además, mientras que /^a/, /^a.*/,
y /^a.*$/
coinciden con cadenas equivalentes, tienen diferentes características de rendimiento. Todas estas expresiones utilizan un índice si existe un índice apropiado; sin embargo, /^a.*/
y /^a.*$/
son mas lentos /^a/
puede dejar de escanear después de hacer coincidir el prefijo.