web-dev-qa-db-fra.com

Effectuer des requêtes regex avec pymongo

J'essaye de faire 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 * Fichier. J'ai essayé de le faire en tant que tel

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

Pourtant, je ne reçois rien en retour, quelque chose me manque, car, selon la documentation de mongodb, cela devrait être possible. Si j'exécute la requête dans la console Mongo, cela fonctionne bien. Cela signifie-t-il que l'API ne la prend pas en charge ou est-ce que je ne l'utilise pas correctement?

119
RC1140

Il s'avère que les recherches sur les expressions rationnelles se font un peu différemment dans pymongo mais sont tout aussi faciles.

La regex se fait comme suit:

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

Cela correspond à tous les documents ayant une propriété files ayant un élément commençant par File.

144
RC1140

Si vous souhaitez inclure des options d’expression régulière (comme ignorer la casse), essayez ceci:

import re
regx = re.compile("^foo", re.IGNORECASE)
db.users.find_one({"files": regx})
175
Eric

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. Ainsi, find_one peut alors détecter l'argument en tant que type 'Regex' et former la requête Mongo appropriée.

Je pense que cette méthode est légèrement plus pythonique que l’autre grande réponse, par exemple:

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

Il vaut la peine de lire la documentation de bson Regex si vous envisagez d’utiliser des requêtes regex, car il y a certaines réserves.

3
Keeely

La solution de re n’utilise pas du tout l’index. Vous devriez utiliser des commandes telles que:

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

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

1
Jeff
import re

def get_pattern_query(pattern,starting_with=False,ending_with=False,ignore_case=False):
    start = '^' if starting_with else '.*'
    end = '$' if ending_with else '.*'
    pattern = start + re.escape(pattern) + end
    return re.compile(pattern, re.IGNORECASE) if ignore_case else re.compile(pattern)

Échappe au motif avant de compiler, gère tous les caractères.

0
daemon24