MongoDB-Abfragen in Python: Filter, Operatoren & Projektion
MongoDB mit Python und pymongo abfragen — Dokumente filtern, Vergleichs- und logische Operatoren nutzen, Felder projizieren und Ergebnisse paginieren.
Dieses Kapitel erklärt, wie man Abfragen in MongoDB mit dem Python-Treiber pymongo erstellt. Sie lernen, Dokumente mit exakten Übereinstimmungen und Vergleichsoperatoren zu filtern, Bedingungen mit logischen Operatoren zu kombinieren, nur die benötigten Felder per Projektion auszuwählen und Ergebnisse mit skip() und limit() zu paginieren.
Falls Sie noch keine Verbindung eingerichtet haben, lesen Sie zunächst MongoDB Get Started und MongoDB Create Collection.
Beispieldaten einrichten
Alle Beispiele in diesem Kapitel verwenden dieselbe customers-Collection. Führen Sie diesen Codeausschnitt einmal aus, um die Daten einzufügen:
import pymongo
client = pymongo.MongoClient("mongodb://localhost:27017/")
db = client["mystore"]
col = db["customers"]
# Drop and re-create so examples are repeatable
col.drop()
col.insert_many([
{"name": "Alice", "age": 30, "city": "London", "score": 88},
{"name": "Bob", "age": 25, "city": "New York", "score": 74},
{"name": "Carol", "age": 35, "city": "London", "score": 91},
{"name": "Dave", "age": 28, "city": "Berlin", "score": 65},
{"name": "Eve", "age": 22, "city": "New York", "score": 77},
])
print("Sample data inserted.")Alle Dokumente abfragen
Der Aufruf von find() mit einem leeren Filter ({}) gibt jedes Dokument der Collection zurück:
for doc in col.find({}):
print(doc)
# {'_id': ..., 'name': 'Alice', 'age': 30, 'city': 'London', 'score': 88}
# {'_id': ..., 'name': 'Bob', 'age': 25, 'city': 'New York', 'score': 74}
# ...Verwenden Sie find_one(), wenn Sie nur das erste übereinstimmende Dokument benötigen:
doc = col.find_one({"city": "London"})
print(doc)
# {'_id': ..., 'name': 'Alice', 'age': 30, 'city': 'London', 'score': 88}find_one() gibt None zurück, wenn kein Dokument übereinstimmt — prüfen Sie das immer, bevor Sie auf Felder zugreifen.
Exakte Übereinstimmungsfilter
Übergeben Sie ein Dictionary an find(), um Dokumente zu finden, bei denen ein Feld einem bestimmten Wert entspricht:
# All customers in London
results = col.find({"city": "London"})
for doc in results:
print(doc["name"], doc["city"])
# Alice London
# Carol LondonMehrere Schlüssel im selben Filter-Dictionary wirken als implizites AND — beide Bedingungen müssen wahr sein:
# Customers in London AND older than 30
results = col.find({"city": "London", "age": {"$gt": 30}})
for doc in results:
print(doc["name"], doc["age"])
# Carol 35Vergleichsoperatoren
MongoDB-Vergleichsoperatoren ermöglichen die Suche nach Dokumenten, bei denen ein Feld in einem bestimmten Bereich oder einer Menge liegt. Alle Operatoren beginnen mit $.
| Operator | Bedeutung | Beispielfilter |
|---|---|---|
$eq | Gleich | {"age": {"$eq": 30}} |
$ne | Ungleich | {"city": {"$ne": "London"}} |
$gt | Größer als | {"score": {"$gt": 80}} |
$gte | Größer oder gleich | {"score": {"$gte": 80}} |
$lt | Kleiner als | {"age": {"$lt": 28}} |
$lte | Kleiner oder gleich | {"age": {"$lte": 28}} |
$in | In einer Liste | {"city": {"$in": ["London", "Berlin"]}} |
$nin | Nicht in einer Liste | {"city": {"$nin": ["London"]}} |
Beispiel — Kunden mit einem Score über 80:
results = col.find({"score": {"$gt": 80}})
for doc in results:
print(doc["name"], doc["score"])
# Alice 88
# Carol 91Beispiel — Kunden zwischen 25 und 30 Jahren (einschließlich):
results = col.find({"age": {"$gte": 25, "$lte": 30}})
for doc in results:
print(doc["name"], doc["age"])
# Alice 30
# Bob 25
# Dave 28Mehrere Operatoren können auf dasselbe Feld in einem einzigen Dictionary angewendet werden, wie oben gezeigt.
Beispiel — Kunden in London oder Berlin:
results = col.find({"city": {"$in": ["London", "Berlin"]}})
for doc in results:
print(doc["name"], doc["city"])
# Alice London
# Carol London
# Dave BerlinLogische Operatoren
Verwenden Sie $and, $or und $nor, wenn Sie Bedingungen auf eine Weise kombinieren müssen, die mit einfachen Dictionary-Schlüsseln nicht möglich ist.
$or — mindestens eine Bedingung muss zutreffen
# Customers younger than 25 OR with a score above 90
results = col.find({"$or": [{"age": {"$lt": 25}}, {"score": {"$gt": 90}}]})
for doc in results:
print(doc["name"], doc["age"], doc["score"])
# Carol 35 91
# Eve 22 77$and — verwenden, wenn zwei verschiedene Operatoren auf dasselbe Feld angewendet werden
Das implizite AND (mehrere Schlüssel) funktioniert nicht, wenn Sie zwei $-Operatoren auf dasselbe Feld anwenden möchten. Verwenden Sie stattdessen $and:
# Customers whose score is > 65 AND < 90
# (cannot use {"score": {"$gt": 65}, "score": {"$lt": 90}} — duplicate key)
results = col.find({"$and": [{"score": {"$gt": 65}}, {"score": {"$lt": 90}}]})
for doc in results:
print(doc["name"], doc["score"])
# Alice 88
# Bob 74
# Eve 77$nor — keine der Bedingungen darf zutreffen
# Customers who are NOT in London AND do NOT have score > 80
results = col.find({"$nor": [{"city": "London"}, {"score": {"$gt": 80}}]})
for doc in results:
print(doc["name"], doc["city"], doc["score"])
# Bob New York 74
# Dave Berlin 65
# Eve New York 77$not — einen einzelnen Feldausdruck negieren
$not kapselt einen einzelnen Operatorausdruck und gibt Dokumente zurück, bei denen die Bedingung falsch ist oder das Feld nicht existiert:
# Customers who do NOT have a score greater than 80
results = col.find({"score": {"$not": {"$gt": 80}}})
for doc in results:
print(doc["name"], doc["score"])
# Bob 74
# Dave 65
# Eve 77Filter mit regulären Ausdrücken
Verwenden Sie den Operator $regex (oder übergeben Sie ein kompiliertes re-Muster), um Teilstring- oder Musterabgleiche auf string-Feldern durchzuführen:
import re
# Customers whose name starts with a vowel
results = col.find({"name": {"$regex": "^[AEIOU]", "$options": "i"}})
for doc in results:
print(doc["name"])
# Alice
# Eve$options: "i" macht den Abgleich case-insensitiv. Vermeiden Sie führende Wildcard-Muster wie .*text bei großen Collections — sie können keinen Index nutzen und führen zu einem vollständigen Collection-Scan.
Projektion — Nur bestimmte Felder zurückgeben
Standardmäßig gibt find() jedes Feld im Dokument zurück, einschließlich _id. Verwenden Sie ein zweites Argument (die Projektion), um Felder ein- oder auszuschließen.
Bestimmte Felder einschließen
Übergeben Sie 1 für jedes gewünschte Feld. Nur diese Felder (plus _id) werden zurückgegeben:
# Return only name and score
results = col.find({}, {"name": 1, "score": 1})
for doc in results:
print(doc)
# {'_id': ..., 'name': 'Alice', 'score': 88}
# {'_id': ..., 'name': 'Bob', 'score': 74}
# ...Bestimmte Felder ausschließen
Übergeben Sie 0 für jedes Feld, das ausgeblendet werden soll. Alle anderen Felder werden zurückgegeben:
# Hide _id and city
results = col.find({}, {"_id": 0, "city": 0})
for doc in results:
print(doc)
# {'name': 'Alice', 'age': 30, 'score': 88}
# {'name': 'Bob', 'age': 25, 'score': 74}
# ...In derselben Projektion können 1 und 0 nicht gemischt werden (außer bei _id, das immer zusammen mit Inklusionen auf 0 gesetzt werden kann).
Ergebnisse sortieren
Hängen Sie .sort() an den Cursor an, um Ergebnisse zu ordnen. Verwenden Sie pymongo.ASCENDING (1) oder pymongo.DESCENDING (-1):
import pymongo
# Sort by score descending
results = col.find({}, {"_id": 0, "name": 1, "score": 1}).sort("score", pymongo.DESCENDING)
for doc in results:
print(doc["name"], doc["score"])
# Carol 91
# Alice 88
# Eve 77
# Bob 74
# Dave 65Übergeben Sie eine Liste von (Feld, Richtung)-Tupeln, um nach mehreren Feldern zu sortieren:
# Sort by city ascending, then by age descending within each city
results = col.find({}, {"_id": 0, "name": 1, "city": 1, "age": 1}).sort(
[("city", pymongo.ASCENDING), ("age", pymongo.DESCENDING)]
)
for doc in results:
print(doc["city"], doc["name"], doc["age"])
# Berlin Dave 28
# London Carol 35
# London Alice 30
# New York Bob 25 <- Bob (25) vs Eve (22): descending so 25 first
# New York Eve 22Weitere Informationen zu Sortieroptionen finden Sie unter MongoDB Sort.
Ergebnisse begrenzen und paginieren
limit()
limit(n) stoppt den Cursor nach der Rückgabe von n Dokumenten:
# Top 3 by score
results = col.find({}, {"_id": 0, "name": 1, "score": 1}).sort("score", -1).limit(3)
for doc in results:
print(doc["name"], doc["score"])
# Carol 91
# Alice 88
# Eve 77skip() für die Paginierung
Kombinieren Sie skip() und limit(), um eine einfache seitenweise Navigation zu implementieren:
page_size = 2
page = 1 # zero-indexed
results = (
col.find({}, {"_id": 0, "name": 1, "score": 1})
.sort("score", -1)
.skip(page * page_size)
.limit(page_size)
)
for doc in results:
print(doc["name"], doc["score"])
# Eve 77 (page 1, items 3–4 of the sorted list)
# Bob 74Bei großen Collections empfiehlt sich die bereichsbasierte Paginierung — filtern Sie anhand der zuletzt gesehenen _id oder eines Zeitstempels — da skip() intern trotzdem über übersprungene Dokumente iteriert.
Weitere Details finden Sie unter MongoDB Limit.
Dokumente zählen
Verwenden Sie count_documents() mit demselben Filter-Dictionary, um Dokumente zu zählen, ohne Daten abzurufen:
total = col.count_documents({})
london = col.count_documents({"city": "London"})
print(f"Total: {total}, In London: {london}")
# Total: 5, In London: 2Vermeiden Sie das veraltete cursor.count() — es wurde in PyMongo 4 entfernt.
Häufige Fehlerquellen
PyMongo-Cursor sind nach der Iteration erschöpft. Sobald Sie einen Cursor durchlaufen haben, ist er leer. Speichern Sie die Ergebnisse in einer Liste, wenn Sie mehr als einmal iterieren müssen:
docs = list(col.find({"city": "London"}))
print(len(docs)) # 2
print(docs[0]["name"]) # Alice_id ist ein ObjectId, kein string. Wenn Sie eine _id als string speichern und später danach abfragen, gibt die Abfrage nichts zurück. Importieren Sie ObjectId aus bson, um zu konvertieren:
from bson import ObjectId
doc = col.find_one({"_id": ObjectId("665000000000000000000001")})Abfragen sind standardmäßig case-sensitiv. {"city": "london"} stimmt nicht mit Dokumenten überein, die als "London" gespeichert sind. Verwenden Sie $regex mit $options: "i" für case-insensitiven Abgleich, oder normalisieren Sie Werte beim Einfügen.
Nächste Schritte
- MongoDB Find —
find()undfind_one()im Detail - MongoDB Sort — Mehrspaltige Sortierung und Index-Hinweise
- MongoDB Limit — Ergebnismenge steuern
- MongoDB Update — Dokumente nach dem Finden ändern
- MongoDB Delete — Dokumente aus einer Collection entfernen