Regex-Abfragen mit Pymongo durchführen

129

Ich versuche, eine Regex-Abfrage mit Pymongo gegen einen Mongodb-Server durchzuführen. Die Dokumentstruktur ist wie folgt

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

Ich möchte alle Dateien erhalten, die dem Muster * File entsprechen. Ich habe versucht, dies als solches zu tun

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

Trotzdem bekomme ich nichts zurück, vermisse ich etwas, denn laut den Mongodb-Dokumenten sollte dies möglich sein. Wenn ich die Abfrage in der Mongo-Konsole durchführe, funktioniert sie einwandfrei. Bedeutet dies, dass die API sie nicht unterstützt oder verwende ich sie nur falsch?

RC1140
quelle

Antworten:

191

Wenn Sie Optionen für reguläre Ausdrücke einschließen möchten (z. B. Groß- / Kleinschreibung ignorieren), versuchen Sie Folgendes:

import re
regx = re.compile("^foo", re.IGNORECASE)
db.users.find_one({"files": regx})
Eric
quelle
8
Beachten Sie auch, dass am Anfang verankerte Regex- ^Indizes (dh beginnend mit ) Indizes in der Datenbank verwenden können und in diesem Fall viel schneller ausgeführt werden.
Drevicko
1
Regex, das mit ^ beginnt, kann nur in bestimmten Fällen einen Index verwenden . Bei Verwendung von re.IGNORECASE kann Mongo meines Erachtens keinen Index verwenden, um die Abfrage durchzuführen.
Nonagon
Ist diese Verwendung irgendwo dokumentiert? Ich kann dies nicht im offiziellen Pymongo-API-Dokument finden.
Hieu
153

Es stellt sich heraus, dass Regex-Suchen in Pymongo etwas anders durchgeführt werden, aber genauso einfach sind.

Regex wird wie folgt durchgeführt:

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

Dies stimmt mit allen Dokumenten überein, die eine Dateieigenschaft haben, in der sich ein Element befindet, das mit Datei beginnt

RC1140
quelle
9
Was Sie hier haben, ist auch die Art und Weise, wie es in Javascript (und wahrscheinlich auch in anderen Sprachen) gemacht wird, wenn Sie es verwenden $regex. @ Erics Antwort ist die Python-Art, die etwas anders ist.
Drevicko
was ist der Unterschied? Sie verwenden beide Python Pymongo richtig? Es ist Teil von Mongodb-Abfragen, daher sehe ich das Problem nicht wirklich.
Dexter
10
Ignorieren ist in Regex von Mongodb JScript auch möglich, nämlich. db.collectionname.find ({'files': {'$ regex': '^ File', '$ options': 'i'}})
Ajay Gupta
5
Diese Antwort sieht für meine Augen besser aus. Warum sollten Sie sich die Mühe machen, eine Python-RE zu kompilieren, wenn Sie sie nur stringifizieren möchten, damit Mongo sie erneut kompilieren kann? Mongos $regexOperator nimmt ein $optionsArgument an.
Mark E. Haase
3
Bitte verwenden Sie r'^File'anstelle von '^File', um andere Probleme zu vermeiden
Aminah Nuraini
9

Um die doppelte Kompilierung zu vermeiden, können Sie den mit PyMongo gelieferten bson regex-Wrapper verwenden:

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

Regex speichert nur die Zeichenfolge, ohne zu versuchen, sie zu kompilieren, sodass find_one das Argument dann als 'Regex'-Typ erkennen und die entsprechende Mongo-Abfrage bilden kann.

Ich denke, dieser Weg ist etwas pythonischer als die andere Top-Antwort, z.

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

Es lohnt sich, die bson Regex-Dokumentation zu lesen, wenn Sie Regex-Abfragen verwenden möchten, da einige Einschränkungen bestehen.

Keeely
quelle
1
Wenn Sie ein Array mit $ in gegen ein Array abgleichen müssen, funktioniert $ regex für Sie nicht. bson.regex.Regex wird den Trick machen!
odedfos
4

Die Lösung von reverwendet den Index überhaupt nicht. Sie sollten Befehle verwenden wie:

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

(Ich kann ihre Antworten nicht kommentieren, also antworte ich hier)

Jeff
quelle