Wykonywanie zapytań regex za pomocą pymongo

132

Próbuję wykonać zapytanie regex przy użyciu pymongo na serwerze mongodb. Struktura dokumentu jest następująca

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

Chcę uzyskać wszystkie pliki, które pasują do wzorca * Plik. Próbowałem to zrobić jako taki

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

Jednak nic nie otrzymuję, brakuje mi czegoś, ponieważ zgodnie z dokumentacją mongodb powinno to być możliwe. Jeśli wykonam zapytanie w konsoli mongo, działa dobrze, czy to oznacza, że ​​api go nie obsługuje, czy po prostu używam go nieprawidłowo

RC1140
źródło

Odpowiedzi:

192

Jeśli chcesz dołączyć opcje wyrażeń regularnych (takie jak ignorowanie wielkości liter), spróbuj tego:

import re
regx = re.compile("^foo", re.IGNORECASE)
db.users.find_one({"files": regx})
Eric
źródło
8
Zauważ również, że wyrażenia regularne zakotwiczone na początku (tj. Zaczynające się od ^) mogą używać indeksów w bazie danych i będą w takim przypadku działać znacznie szybciej.
drevicko
1
Regex zaczynający się od ^ może używać indeksu tylko w niektórych przypadkach . Podczas korzystania z re.IGNORECASE uważam, że mongo nie może użyć indeksu do wykonania zapytania.
nonagon
Czy to użycie jest gdzieś udokumentowane? Nie mogę znaleźć tego w oficjalnym dokumencie API pymongo.
Hieu
154

Okazuje się, że wyszukiwanie wyrażeń regularnych odbywa się nieco inaczej w pymongo, ale jest równie łatwe.

Regex jest wykonywany w następujący sposób:

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

Spowoduje to dopasowanie wszystkich dokumentów, które mają właściwość files, w której znajduje się element rozpoczynający się od pliku

RC1140
źródło
9
Właściwie masz tutaj również sposób, w jaki jest to zrobione w javascript (i prawdopodobnie także w innych językach), jeśli używasz $regex. @ Eric odpowiada nieco inaczej w języku Pythona.
drevicko
co za różnica? Oboje używają Pythona pymongo, prawda? Jest to część zapytań mongodb, więc tak naprawdę nie widzę problemu.
Dexter
10
Ignorecase jest możliwe w wyrażeniu regularnym mongodb JScript, a mianowicie. db.collectionname.find ({'files': {'$ regex': '^ File', '$ options': 'i'}})
Ajay Gupta
5
Ta odpowiedź wygląda lepiej w moich oczach. Po co zawracać sobie głowę kompilacją Pythona RE, jeśli zamierzasz go po prostu dodać, aby Mongo mógł go ponownie skompilować? $regexOperator Mongo przyjmuje $optionsargument.
Mark E. Haase
3
Użyj r'^File'zamiast, '^File'aby uniknąć innego problemu
Aminah Nuraini
10

Aby uniknąć podwójnej kompilacji, możesz użyć opakowania wyrażeń regularnych bson, które jest dostarczane z PyMongo:

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

Regex po prostu przechowuje ciąg bez próby jego kompilacji, więc find_one może następnie wykryć argument jako typ „Regex” i utworzyć odpowiednie zapytanie Mongo.

Wydaje mi się, że ten sposób jest nieco bardziej Pythonic niż inna najlepsza odpowiedź, np:

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

Warto przeczytać dokumentację bson Regex, jeśli planujesz używać zapytań regex, ponieważ istnieją pewne zastrzeżenia.

Keeely
źródło
2
Jeśli potrzebujesz dopasować do tablicy przy użyciu $ in, to $ regex nie zadziała. bson.regex.Regex da rade!
odedfos
4

Rozwiązanie w reogóle nie używa indeksu. Powinieneś używać poleceń takich jak:

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

(Nie mogę komentować poniżej ich odpowiedzi, więc odpowiadam tutaj)

Jeff
źródło