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

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})

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


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.


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)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.