length - Longitud del valor del campo de cadena en mongoDB
mongodb where length (4)
El tipo de datos del campo es Cadena. Me gustaría obtener los datos donde la longitud de los caracteres del nombre del campo es mayor que 40.
Intenté estas consultas pero devolví el error. 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
}
esto funciona en 2.4.9 Pero mi versión es 2.6.5
Esta es una de las formas en que mongodb puede lograr esto.
db.usercollection.find({ $where: ''this.name.length < 4'' })
Las consultas con
$where
y
$expr
son lentas si hay demasiados documentos.
Usar
$regex
es mucho más rápido que
$where
,
$expr
.
db.usercollection.find({
"name": /^[/s/S]{40,}$/, // name.length >= 40
})
or
db.usercollection.find({
"name": { "$regex": "^[/s/S]{40,}$" }, // name.length >= 40
})
Esta consulta tiene el mismo significado con
db.usercollection.find({
"$where": "this.name && this.name.length >= 40",
})
or
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gte": [ { "$strLenCP": "$name" }, 40 ] }
})
Probé cada consulta para mi colección.
# find
$where: 10529.359ms
$expr: 5305.801ms
$regex: 2516.124ms
# count
$where: 10872.006ms
$expr: 2630.155ms
$regex: 158.066ms
Tuve un tipo similar de escenario, pero en mi caso la cadena no es un atributo de primer nivel. Está dentro de un objeto. Aquí no pude encontrar una respuesta adecuada para ello. Así que pensé en compartir mi solución con todos ustedes (espero que esto ayude a cualquiera con un tipo de problema similar).
Parent Collection
{
"Child":
{
"name":"Random Name",
"Age:"09"
}
}
Ej: si necesitamos obtener solo colecciones que tengan la longitud del nombre del niño mayor de 10 caracteres.
db.getCollection(''Parent'').find({$where: function() {
for (var field in this.Child.name) {
if (this.Child.name.length > 10)
return true;
}
}})
Para MongoDB 3.6 y más reciente:
El operador
$expr
permite el uso de expresiones de agregación dentro del lenguaje de consulta, por lo tanto, puede aprovechar el uso del operador
$strLenCP
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 más reciente:
También puede usar el marco de agregación con el operador de canalización
$redact
que le permite procesar la condición lógica con el operador
$cond
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 una canalización de
$project
que selecciona los campos de la colección y crea un nuevo campo que contiene el resultado de la consulta de condición lógica y luego una
$match
posterior, excepto que
$redact
usa 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 el operador
$strLenCP
para verificar la longitud de la cadena.
Si la longitud es
$gt
un valor especificado, entonces esta es una coincidencia real y el documento se "mantiene".
De lo contrario, se "poda" y se descarta.
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:
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 las operaciones de consulta que no son
$where
antes
$where
expresiones
$where
y las declaraciones de consulta non-
$where
pueden usar un índice.
Un rendimiento mucho mejor es almacenar la longitud de la cadena como otro campo y luego puede indexarla o buscarla;
aplicar
$where
será mucho más lento en comparación con eso.
Se recomienda utilizar expresiones de JavaScript y el operador
$where
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
operator es el operador
$regex
.
Considere el siguiente patrón que busca
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
Nota - De los docs :
Si existe un índice para el campo, MongoDB compara la expresión regular con los valores del índice, que puede ser más rápido que un análisis de recopilación. Se puede lograr 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 un símbolo de intercalación
(^)
o un ancla izquierda(/A)
, seguida de una cadena de símbolos simples. Por ejemplo, la expresión regular/^abc.*/
se optimizará haciendo coincidir solo los valores del índice que comienzan conabc
.Además, aunque
/^a/, /^a.*/,
y/^a.*$/
coinciden con cadenas equivalentes, tienen características de rendimiento diferentes. Todas estas expresiones usan un índice si existe un índice apropiado; sin embargo,/^a.*/
y/^a.*$/
son más lentos./^a/
puede detener el escaneo después de hacer coincidir el prefijo.