Realizar consultas regex con pymongo

129

Estoy tratando de realizar una consulta de expresiones regulares usando pymongo contra un servidor mongodb. La estructura del documento es la siguiente

{
  "files": [
    "File 1",
    "File 2",
    "File 3",
    "File 4"
  ],
  "rootFolder": "/Location/Of/Files"
}

Quiero obtener todos los archivos que coinciden con el patrón * Archivo. Traté de hacer esto como tal

db.collectionName.find({'files':'/^File/'})

Sin embargo, no recibo nada, me estoy perdiendo algo porque, según los documentos de mongodb, esto debería ser posible. Si realizo la consulta en la consola mongo, funciona bien, ¿significa que la API no es compatible o simplemente la estoy usando incorrectamente?

RC1140
fuente

Respuestas:

191

Si desea incluir opciones de expresión regular (como ignorar mayúsculas y minúsculas), intente esto:

import re
regx = re.compile("^foo", re.IGNORECASE)
db.users.find_one({"files": regx})
Eric
fuente
8
Tenga en cuenta también que las expresiones regulares ancladas al comienzo (es decir, comenzando con ^) pueden usar índices en la base de datos, y en ese caso se ejecutarán mucho más rápido.
drevicko
1
Regex que comienza con ^ solo puede usar un índice en ciertos casos . Al usar re.IGNORECASE, creo que mongo no puede usar un índice para realizar la consulta.
nonagon
¿Está documentado este uso en alguna parte? No puedo encontrar esto en el documento oficial de Pymongo API.
Hieu
153

Resulta que las búsquedas de expresiones regulares se realizan de manera un poco diferente en Pymongo, pero es igual de fácil.

Regex se realiza de la siguiente manera:

db.collectionname.find({'files':{'$regex':'^File'}})

Esto coincidirá con todos los documentos que tienen una propiedad de archivos que tiene un elemento que comienza con Archivo

RC1140
fuente
9
En realidad, lo que tienes aquí también es la forma en que se hace en JavaScript (y probablemente también en otros idiomas) si lo usas $regex. La respuesta de @ Eric es la forma de Python que es un poco diferente.
drevicko
¿cual es la diferencia? Ambos están usando python pymongo ¿correcto? Es parte de las consultas mongodb, así que no veo el problema realmente.
Dexter
10
Ignorecase es posible en regex de mongodb JScript también a saber. db.collectionname.find ({'archivos': {'$ regex': '^ Archivo', '$ opciones': 'i'}})
Ajay Gupta
55
Esta respuesta se ve mejor a mis ojos. ¿Por qué molestarse en compilar un Python RE si solo va a encadenarlo para que Mongo pueda compilarlo nuevamente? El $regexoperador de Mongo toma una $optionsdiscusión.
Mark E. Haase
3
Por favor, use r'^File'en lugar de '^File'evitar otro problema
Amina Nuraini
9

Para evitar la doble compilación, puede usar el contenedor bson regex que viene con PyMongo:

>>> regx = bson.regex.Regex('^foo')
>>> db.users.find_one({"files": regx})

Regex simplemente almacena la cadena sin intentar compilarla, por lo que find_one puede detectar el argumento como un tipo 'Regex' y formar la consulta Mongo adecuada.

Siento que de esta manera es un poco más Pythonic que la otra respuesta principal, por ejemplo:

>>> db.collectionname.find({'files':{'$regex':'^File'}})

Vale la pena leer la documentación de bson Regex si planea usar consultas de expresiones regulares porque hay algunas advertencias.

Keeely
fuente
1
Si necesita hacer coincidir una matriz con $ in, entonces $ regex no funcionaría para usted. bson.regex.Regex hará el truco!
odedfos
4

La solución de reno usa el índice en absoluto. Deberías usar comandos como:

db.collectionname.find({'files':{'$regex':'^File'}})

(No puedo comentar debajo de sus respuestas, así que respondo aquí)

Jeff
fuente