Exécution de requêtes regex avec pymongo

129

J'essaye d'effectuer une requête regex en utilisant pymongo contre un serveur mongodb. La structure du document est la suivante

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

Je veux obtenir tous les fichiers qui correspondent au modèle * File. J'ai essayé de faire ça comme tel

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

Pourtant, je ne reçois rien en retour, est-ce que je manque quelque chose parce que selon la documentation de mongodb cela devrait être possible. Si j'exécute la requête dans la console mongo, cela fonctionne correctement, cela signifie-t-il que l'api ne le prend pas en charge ou est-ce que je l'utilise simplement de manière incorrecte?

RC1140
la source

Réponses:

191

Si vous souhaitez inclure des options d'expressions régulières (telles que Ignorer la casse), essayez ceci:

import re
regx = re.compile("^foo", re.IGNORECASE)
db.users.find_one({"files": regx})
Eric
la source
8
Notez également que les expressions régulières ancrées au début (c'est-à-dire commençant par ^) peuvent utiliser des index dans la base de données, et fonctionneront beaucoup plus rapidement dans ce cas.
drevicko
1
Les expressions régulières commençant par ^ ne peuvent utiliser un index que dans certains cas . Lors de l'utilisation de re.IGNORECASE, je crois que mongo ne peut pas utiliser un index pour effectuer la requête.
nonagon
Cette utilisation est-elle documentée quelque part? Je ne trouve pas cela dans la documentation officielle de l'API pymongo.
Hieu
153

Il s'avère que les recherches regex sont effectuées un peu différemment dans pymongo, mais elles sont tout aussi faciles.

Regex se fait comme suit:

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

Cela correspondra à tous les documents dont la propriété files contient un élément commençant par File

RC1140
la source
9
En fait, ce que vous avez ici, c'est aussi la façon dont c'est fait en javascript (et probablement dans d'autres langues aussi) si vous utilisez $regex. La réponse de @ Eric est la manière python qui est un peu différente.
drevicko
quelle est la différence? Ils utilisent tous les deux python pymongo, n'est-ce pas? Cela fait partie des requêtes mongodb, donc je ne vois pas vraiment le problème.
Dexter
10
Ignorecase est possible dans regex de mongodb JScript également à savoir. db.collectionname.find ({'files': {'$ regex': '^ File', '$ options': 'i'}})
Ajay Gupta
5
Cette réponse me va mieux. Pourquoi se donner la peine de compiler un Python RE si vous allez juste le stringifier pour que Mongo puisse le compiler à nouveau? L' $regexopérateur de Mongo prend un $optionsargument.
Mark E. Haase
3
Veuillez utiliser à la r'^File'place de '^File'pour éviter tout autre problème
Aminah Nuraini
9

Pour éviter la double compilation, vous pouvez utiliser le wrapper bson regex fourni avec PyMongo:

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

Regex stocke simplement la chaîne sans essayer de la compiler, donc find_one peut alors détecter l'argument comme un type 'Regex' et former la requête Mongo appropriée.

Je pense que cette façon est légèrement plus pythonique que l'autre réponse principale, par exemple:

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

Cela vaut la peine de lire la documentation de bson Regex si vous prévoyez d'utiliser des requêtes regex car il y a quelques mises en garde.

Keeely
la source
1
Si vous avez besoin de faire correspondre un tableau en utilisant $ in, alors $ regex ne fonctionnera pas pour vous. bson.regex.Regex fera l'affaire!
odedfos le
4

La solution de ren'utilise pas du tout l'index. Vous devriez utiliser des commandes comme:

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

(Je ne peux pas commenter ci-dessous leurs réponses, donc je réponds ici)

Jeff
la source