Executando consultas regex com pymongo

129

Estou tentando executar uma consulta regex usando o pymongo em um servidor mongodb. A estrutura do documento é a seguinte

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

Quero obter todos os arquivos que correspondam ao padrão * Arquivo. Eu tentei fazer isso como tal

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

No entanto, não recebo nada de volta, estou perdendo alguma coisa porque, de acordo com os documentos do mongodb, isso deve ser possível. Se eu executar a consulta no console mongo, ela funciona bem, isso significa que a API não a suporta ou eu estou apenas usando incorretamente

RC1140
fonte

Respostas:

191

Se você deseja incluir opções de expressão regular (como ignorar maiúsculas e minúsculas), tente o seguinte:

import re
regx = re.compile("^foo", re.IGNORECASE)
db.users.find_one({"files": regx})
Eric
fonte
8
Observe também que os regexs ancorados no início (ou seja: começando com ^) são capazes de usar índices no banco de dados e, nesse caso, serão executados muito mais rapidamente.
precisa saber é o seguinte
1
Regex começando com ^ só pode usar um índice em certos casos . Ao usar re.IGNORECASE, acredito que o mongo não pode usar um índice para realizar a consulta.
Nonagon 8/04
Esse uso está documentado em algum lugar? Não consigo encontrar isso no documento oficial da API do pymongo.
197
153

Acontece que as pesquisas regex são feitas de maneira um pouco diferente no pymongo, mas é igualmente fácil.

Regex é feito da seguinte maneira:

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

Isso corresponderá a todos os documentos que possuem uma propriedade de arquivos que possui um item que começa com Arquivo

RC1140
fonte
9
Na verdade, o que você tem aqui também é como é feito em javascript (e provavelmente em outros idiomas também) se você usar $regex. A resposta de Eric é a maneira python que é um pouco diferente.
drevicko
qual é a diferença? Ambos estão usando python pymongo correto? É parte das consultas do mongodb, então não vejo o problema realmente.
Dexter
10
Ignorecase é possível no regex do mongodb JScript também viz. db.collectionname.find ({'files': {'$ regex': '^ File', '$ options': 'i'}}) ''
Ajay Gupta
5
Esta resposta parece melhor aos meus olhos. Por que se incomodar em compilar um Python RE se você apenas o especificar, para que o Mongo possa compilá-lo novamente? O $regexoperador do Mongo aceita uma $optionsdiscussão.
Mark E. Haase
3
Utilize r'^File'em vez de '^File'evitar outro problema
Aminah Nuraini
9

Para evitar a compilação dupla, você pode usar o wrapper bson regex que acompanha o PyMongo:

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

O Regex apenas armazena a string sem tentar compilá-la, portanto, find_one pode detectar o argumento como um tipo 'Regex' e formar a consulta Mongo apropriada.

Eu sinto que esse caminho é um pouco mais pitônico do que a outra resposta principal, por exemplo:

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

Vale a pena ler na documentação do bson Regex se você planeja usar consultas regex porque existem algumas ressalvas.

Keeely
fonte
1
Se você precisar corresponder novamente a uma matriz usando $ in, $ regex não funcionaria para você. bson.regex.Regex vai fazer o truque!
Odedfos 4/07
4

A solução de renão usa o índice. Você deve usar comandos como:

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

(Não posso comentar abaixo das respostas deles, por isso respondo aqui)

Jeff
fonte