MongoDB expresiones regulares Buscar en valor entero
-
04-10-2019 - |
Pregunta
Quiero regex buscar un valor entero en MongoDB. ¿Es esto posible?
Estoy construyendo una interfaz de tipo CRUD que permite * para comodines en los diversos campos. Estoy tratando de mantener la interfaz de usuario consistente para algunos campos que son números enteros.
Considere lo siguiente:
> db.seDemo.insert({ "example" : 1234 });
> db.seDemo.find({ "example" : 1234 });
{ "_id" : ObjectId("4bfc2bfea2004adae015220a"), "example" : 1234 }
> db.seDemo.find({ "example" : /^123.*/ });
>
Como se puede ver, insertar un objeto y yo soy capaz de encontrarlo por el valor. Si trato de una expresión regular simple, en realidad no puedo encontrar el objeto.
Gracias!
Solución
Si estás interesado en hacer una comparación de patrones en los números, la forma de hacerlo en mongo es utilizar la expresión $ dónde y pasar de una coincidencia de patrón.
> db.test.find({ $where: "/^123.*/.test(this.example)" })
{ "_id" : ObjectId("4bfc3187fec861325f34b132"), "example" : 1234 }
Otros consejos
No soy un gran fan de utilizar el $where
consulta operador debido a la forma en que se evalúa la expresión de consulta, no hace uso de índices y el riesgo de seguridad si la consulta utiliza los datos de entrada del usuario.
A partir de MongoDB 4.2 se puede utilizar el $regexMatch|$regexFind|$regexFindAll
disponible en MongoDB 4.1.9+ y la $expr
para hacer esto.
let regex = /123/;
-
$regexMatch
y$regexFind
db.col.find({ "$expr": { "$regexMatch": { "input": {"$toString": "$name"}, "regex": /123/ } } })
-
$regexFinAll
db.col.find({ "$expr": { "$gt": [ { "$size": { "$regexFindAll": { "input": {"$toString": "$name"}, "regex": "123" } } }, 0 ] } })
A partir de MongoDB 4.0 se puede utilizar el operador $toString
que es una envoltura alrededor del operador $convert
a stringify enteros.
db.seDemo.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": [
{ "$indexOfCP": [
{ "$toString": "$example" },
"123"
] },
-1
] },
"$$KEEP",
"$$PRUNE"
]
}}
])
Si lo que quiere es recuperar todo el documento que contiene una subcadena en particular, a partir de la liberación 3.4, puede utilizar el $redact
operador que permite a un $cond
itional processing.$indexOfCP
lógica.
db.seDemo.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": [
{ "$indexOfCP": [
{ "$toLower": "$example" },
"123"
] },
-1
] },
"$$KEEP",
"$$PRUNE"
]
}}
])
que produce:
{
"_id" : ObjectId("579c668c1c52188b56a235b7"),
"example" : 1234
}
{
"_id" : ObjectId("579c66971c52188b56a235b9"),
"example" : 12334
}
Antes de MongoDB 3.4, es necesario $project
su documento y añadir otro campo calculado que es el valor de la cadena de su número.
El $toLower
y su hermano operadores $toUpper
noreferrer nofollow convertir respectivamente una cadena a minúsculas y mayúsculas, pero tienen una característica poco desconocida que es que se pueden utilizar para convertir un entero en cadena.
$match
operador devuelve todos aquellos documentos que responden a su búsqueda patrón usando el operador $regex
.
db.seDemo.aggregate(
[
{ "$project": {
"stringifyExample": { "$toLower": "$example" },
"example": 1
}},
{ "$match": { "stringifyExample": /^123.*/ } }
]
)
que los rendimientos:
{
"_id" : ObjectId("579c668c1c52188b56a235b7"),
"example" : 1234,
"stringifyExample" : "1234"
}
{
"_id" : ObjectId("579c66971c52188b56a235b9"),
"example" : 12334,
"stringifyExample" : "12334"
}
Ahora, si lo que quiere es recuperar todo el documento que contiene una subcadena en particular, la manera más fácil y mejor de hacer esto es en el próximo lanzamiento de MongoDB (a partir de este escrito) utilizando el $redact
operador que permite a un $cond
itional processing.$indexOfCP
lógica.
db.seDemo.aggregate([
{ "$redact": {
"$cond": [
{ "$gt": [
{ "$indexOfCP": [
{ "$toLower": "$example" },
"123"
] },
-1
] },
"$$KEEP",
"$$PRUNE"
]
}}
])