sql >> Base de Datos >  >> NoSQL >> MongoDB

Longitud del valor del campo de cadena en mongoDB

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.