MongoDB Find
Lernen Sie, MongoDB-Dokumente mit Python abzurufen: find_one(), find(), Projektionen, Abfrageoperatoren, sort, skip und limit mit PyMongo.
Dieses Kapitel erklärt, wie man mit dem Python-Treiber pymongo Dokumente aus einer MongoDB-Collection abruft. Sie lernen die Methoden find_one() und find(), wie man Ergebnisse mit Abfrageoperatoren filtert, wie man mit Projektionen steuert, welche Felder zurückgegeben werden, und wie man Ergebnisse sortiert, überspringt und begrenzt.
Einrichtung
Stellen Sie sicher, dass pymongo installiert ist, bevor Sie ein Beispiel ausführen:
pip install pymongoAlle folgenden Beispiele setzen einen laufenden MongoDB-Server unter mongodb://localhost:27017/ voraus. Um auf Ihrem eigenen Rechner mitzuarbeiten, starten Sie MongoDB mit mongod oder nutzen Sie einen kostenlosen Cloud-Cluster (MongoDB Atlas).
Beispieldaten vorbereiten
Die Beispiele in diesem Kapitel verwenden eine customers-Collection mit diesen fünf Dokumenten. Führen Sie dies einmal aus, um sie zu befüllen:
import pymongo
client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["mydatabase"]
col = db["customers"]
# Insert sample documents (skip if already inserted)
col.drop() # start fresh
col.insert_many([
{"name": "Alice", "age": 28, "city": "London"},
{"name": "Bob", "age": 34, "city": "Paris"},
{"name": "Carol", "age": 22, "city": "London"},
{"name": "David", "age": 40, "city": "Berlin"},
{"name": "Eve", "age": 34, "city": "Paris"},
])
print("Sample data ready.")Erwartete Ausgabe:
Sample data ready.PyMongo fügt jedem Dokument, das noch keines hat, automatisch ein eindeutiges _id-Feld (ein bson.ObjectId) hinzu.
Ein einzelnes Dokument mit find_one() abrufen
find_one() gibt das erste Dokument zurück, das dem Filter entspricht, oder None, wenn kein Dokument übereinstimmt. Es ist die richtige Wahl, wenn Sie genau ein Ergebnis erwarten (zum Beispiel beim Nachschlagen eines Benutzers anhand seiner E-Mail-Adresse).
# Retrieve the first document in the collection
doc = col.find_one()
print(doc)
# {'_id': ObjectId('...'), 'name': 'Alice', 'age': 28, 'city': 'London'}Übergeben Sie einen Filter, um ein bestimmtes Dokument abzugleichen:
# Find the customer named Bob
bob = col.find_one({"name": "Bob"})
print(bob)
# {'_id': ObjectId('...'), 'name': 'Bob', 'age': 34, 'city': 'Paris'}Wenn kein Dokument übereinstimmt, gibt find_one() None zurück, daher sollten Sie immer dagegen absichern:
result = col.find_one({"name": "Zara"})
if result is None:
print("No document found.")Mehrere Dokumente mit find() abrufen
find() gibt einen Cursor zurück — einen verzögerten Iterator über alle übereinstimmenden Dokumente. Vom Server wird nichts abgerufen, bis Sie iterieren.
Alle Dokumente abrufen
# Iterate every document in the collection
for doc in col.find():
print(doc["name"], doc["age"])Erwartete Ausgabe (Reihenfolge kann ohne explizite Sortierung variieren):
Alice 28
Bob 34
Carol 22
David 40
Eve 34Mit einer genauen Übereinstimmung filtern
Übergeben Sie ein Dictionary als erstes Argument an find():
# All customers in London
for doc in col.find({"city": "London"}):
print(doc["name"])
# Alice
# CarolProjektionen — Auswählen der zurückzugebenden Felder
Standardmäßig gibt MongoDB jedes Feld zurück, einschließlich _id. Eine Projektion ermöglicht es Ihnen, bestimmte Felder ein- oder auszuschließen, was den Netzwerkverkehr und den Speicherverbrauch reduziert.
Übergeben Sie die Projektion als zweites Positionsargument (oder als Schlüsselwortargument projection):
# Return only name and city; suppress _id
for doc in col.find({}, {"_id": 0, "name": 1, "city": 1}):
print(doc)
# {'name': 'Alice', 'city': 'London'}
# {'name': 'Bob', 'city': 'Paris'}
# ...Regeln für Projektionen:
- Verwenden Sie
1, um ein Feld einzuschließen, und0, um es auszuschließen. - Sie können Inklusion und Exklusion nicht in derselben Projektion mischen, außer bei
_id(das immer explizit auf0gesetzt werden kann).
Abfrageoperatoren
MongoDB bietet eine umfangreiche Auswahl an Operatoren zum Filtern von Dokumenten. Übergeben Sie diese innerhalb des Filter-Dictionarys.
Vergleichsoperatoren
| Operator | Bedeutung | Beispiel |
|---|---|---|
$eq | Gleich (Standard) | {"age": {"$eq": 34}} |
$ne | Ungleich | {"city": {"$ne": "Paris"}} |
$gt | Größer als | {"age": {"$gt": 30}} |
$gte | Größer als oder gleich | {"age": {"$gte": 34}} |
$lt | Kleiner als | {"age": {"$lt": 30}} |
$lte | Kleiner als oder gleich | {"age": {"$lte": 28}} |
$in | Wert in Liste | {"city": {"$in": ["London", "Berlin"]}} |
$nin | Wert nicht in Liste | {"city": {"$nin": ["Paris"]}} |
Beispiel — Kunden älter als 30:
for doc in col.find({"age": {"$gt": 30}}, {"_id": 0, "name": 1, "age": 1}):
print(doc)
# {'name': 'Bob', 'age': 34}
# {'name': 'David', 'age': 40}
# {'name': 'Eve', 'age': 34}Beispiel — Kunden in London oder Berlin:
for doc in col.find(
{"city": {"$in": ["London", "Berlin"]}},
{"_id": 0, "name": 1, "city": 1}
):
print(doc)
# {'name': 'Alice', 'city': 'London'}
# {'name': 'Carol', 'city': 'London'}
# {'name': 'David', 'city': 'Berlin'}Logische Operatoren
Implizites AND — wenn mehrere Schlüssel in einem einzigen Filter-Dictionary angegeben werden, müssen alle Bedingungen zutreffen:
# Age > 30 AND city is Paris
for doc in col.find({"age": {"$gt": 30}, "city": "Paris"}, {"_id": 0}):
print(doc)
# {'name': 'Bob', 'age': 34, 'city': 'Paris'}
# {'name': 'Eve', 'age': 34, 'city': 'Paris'}$and ist erforderlich, wenn Sie zwei verschiedene Bedingungen auf dasselbe Feld anwenden möchten:
# Age between 28 (inclusive) and 40 (exclusive)
query = {"$and": [{"age": {"$gte": 28}}, {"age": {"$lt": 40}}]}
for doc in col.find(query, {"_id": 0, "name": 1, "age": 1}):
print(doc)
# {'name': 'Alice', 'age': 28}
# {'name': 'Bob', 'age': 34}
# {'name': 'Eve', 'age': 34}$or — mindestens eine Bedingung muss zutreffen:
# City is Berlin OR age is 22
for doc in col.find(
{"$or": [{"city": "Berlin"}, {"age": 22}]},
{"_id": 0, "name": 1}
):
print(doc)
# {'name': 'Carol'}
# {'name': 'David'}Musterabgleich mit $regex
Verwenden Sie $regex, um string-Felder mit einem regulären Ausdruck abzugleichen:
# Names that start with the letter 'C' or 'E' (case-sensitive)
for doc in col.find({"name": {"$regex": "^[CE]"}}, {"_id": 0, "name": 1}):
print(doc)
# {'name': 'Carol'}
# {'name': 'Eve'}Für die Groß-/Kleinschreibung-unabhängige Suche fügen Sie $options: "i" hinzu:
for doc in col.find(
{"city": {"$regex": "london", "$options": "i"}},
{"_id": 0, "name": 1, "city": 1}
):
print(doc)
# {'name': 'Alice', 'city': 'London'}
# {'name': 'Carol', 'city': 'London'}Ergebnisse sortieren
Verketten Sie .sort() an den Cursor. Übergeben Sie den Feldnamen und eine Richtungskonstante:
pymongo.ASCENDING(oder1) — A → Z, vom kleinsten zum größtenpymongo.DESCENDING(oder-1) — Z → A, vom größten zum kleinsten
# Sort by age ascending
for doc in col.find({}, {"_id": 0, "name": 1, "age": 1}).sort("age", pymongo.ASCENDING):
print(doc)
# {'name': 'Carol', 'age': 22}
# {'name': 'Alice', 'age': 28}
# {'name': 'Bob', 'age': 34}
# {'name': 'Eve', 'age': 34}
# {'name': 'David', 'age': 40}Sortieren Sie nach mehreren Feldern, indem Sie eine Liste von (Feld, Richtung)-Tupeln übergeben:
# Sort by age descending, then by name ascending (tiebreak)
order = [("age", pymongo.DESCENDING), ("name", pymongo.ASCENDING)]
for doc in col.find({}, {"_id": 0, "name": 1, "age": 1}).sort(order):
print(doc)
# {'name': 'David', 'age': 40}
# {'name': 'Bob', 'age': 34}
# {'name': 'Eve', 'age': 34}
# {'name': 'Alice', 'age': 28}
# {'name': 'Carol', 'age': 22}Ergebnisse begrenzen
.limit(n) begrenzt die Anzahl der zurückgegebenen Dokumente. Dies ist nützlich, um die obersten N Ergebnisse anzuzeigen.
# Top 3 youngest customers
for doc in col.find({}, {"_id": 0, "name": 1, "age": 1}).sort("age", 1).limit(3):
print(doc)
# {'name': 'Carol', 'age': 22}
# {'name': 'Alice', 'age': 28}
# {'name': 'Bob', 'age': 34}Dokumente überspringen (Paginierung)
.skip(n) überspringt die ersten n Dokumente. In Kombination mit .limit() ermöglicht dies eine seitenbasierte Paginierung:
PAGE_SIZE = 2
def get_page(page_number):
"""Return one page of customers sorted by age (page_number is 0-indexed)."""
return list(
col.find({}, {"_id": 0, "name": 1, "age": 1})
.sort("age", pymongo.ASCENDING)
.skip(page_number * PAGE_SIZE)
.limit(PAGE_SIZE)
)
print(get_page(0)) # [{'name': 'Carol', 'age': 22}, {'name': 'Alice', 'age': 28}]
print(get_page(1)) # [{'name': 'Bob', 'age': 34}, {'name': 'Eve', 'age': 34}]
print(get_page(2)) # [{'name': 'David', 'age': 40}]Bei großen Collections bevorzugen Sie die cursor-basierte Paginierung (Filtern nach der zuletzt gesehenen _id) gegenüber skip(), da skip() Dokumente scannen und verwerfen muss, was mit wachsendem Offset langsamer wird.
Übereinstimmende Dokumente zählen
Verwenden Sie count_documents() mit einem Filter, um Treffer zu zählen, ohne die Dokumente abzurufen:
london_count = col.count_documents({"city": "London"})
print(london_count) # 2
total = col.count_documents({})
print(total) # 5Vermeiden Sie die ältere .count()-Methode bei Cursors — sie wurde in PyMongo 3.7 als veraltet markiert und in PyMongo 4 entfernt.
Prüfen, ob ein Dokument vorhanden ist
Wenn Sie nur wissen möchten, ob mindestens ein Dokument übereinstimmt, verwenden Sie find_one() (günstiger als das Zählen):
exists = col.find_one({"city": "Berlin"}) is not None
print(exists) # TrueHäufige Fallstricke
Der Cursor ist nach einer Iteration erschöpft. Wenn Sie denselben Cursor zweimal iterieren, produziert die zweite Schleife nichts. Rufen Sie find() erneut auf oder konvertieren Sie in eine Liste:
cursor = col.find({"city": "Paris"})
results = list(cursor) # materialise once
print(len(results)) # 2
# Now you can iterate `results` as many times as you likefind_one() vs. find() — wählen Sie das Richtige. Wenn Sie wissen, dass es höchstens eine Übereinstimmung gibt (zum Beispiel beim Abfragen nach einem eindeutigen Feld wie E-Mail), verwenden Sie find_one(). Mit find() müssen Sie iterieren, auch wenn Sie nur ein Ergebnis benötigen.
None-Filter vs. leeres Dict. Sowohl find() als auch find({}) geben alle Dokumente zurück. Vermeiden Sie es, None explizit zu übergeben — verwenden Sie {} für Klarheit.
Verwandte Kapitel
- MongoDB Insert — Dokumente in eine Collection einfügen, bevor Sie sie abfragen
- MongoDB Query — tiefere Behandlung von Abfrageausdrücken und Filtermustern
- MongoDB Sort — dedizierte Behandlung der Mehrspalten-Sortierung
- MongoDB Limit — limit und seine Interaktion mit Indizes
- MongoDB Update — gefundene Dokumente ändern
- MongoDB Delete — übereinstimmende Dokumente entfernen