HOWTO · MongoDB

Abfrage mit mehreren Bedingungen in MongoDB

In diesem Lehrbeitrag erfahren Sie, welche Operatoren verwendet werden können, um mehrere Dokumente zu mehreren Bedingungen in MongoDB zu finden und abzufragen. $and- und $or-Operatoren werden kurz beschrieben.

Auf dieser Seite

Verwenden Sie find() mit einem Filterdokument, um MongoDB anhand mehrerer Bedingungen abzufragen. Felder im selben Filter werden standardmäßig mit AND verknüpft. Verwenden Sie $or, wenn mindestens eine der aufgeführten Klauseln zutreffen darf, $and, wenn jede Klausel zutreffen muss, und $in für mehrere Gleichheitswerte eines Feldes.

So kombiniert MongoDB Abfragebedingungen

Ein Abfragefilter legt fest, welche Dokumente zurückgegeben werden. Die Abfrage db.inventory.find({ quantity: { $gt: 10 }, price: { $lt: 20 } }) findet beispielsweise Bestandsdokumente, deren Menge größer als 10 und deren Preis kleiner als 20 ist. MongoDB verknüpft diese Bedingungen für die einzelnen Felder implizit mit AND. Für diesen Fall ist daher kein explizites $and erforderlich.

Die folgenden Shell-Beispiele setzen voraus, dass db.inventory diese drei Dokumente enthält: { item: "notebook", quantity: 30, price: 12 }, { item: "pen", quantity: 80, price: 20 } und { item: "folder", quantity: 80, price: 8 }. Die erste Abfrage findet das Notebook und den Ordner: Bei beiden ist die Menge größer als 10 und der Preis kleiner als 20. Der Preis des Stifts beträgt 20, daher erfüllt er die Preisbedingung nicht. Dasselbe gilt, wenn Sie dem Filter weitere Felder hinzufügen: Jede Bedingung muss zutreffen. Ein einfacher Filter ist somit der klarste Ausgangspunkt für Abfragen, bei denen „all diese Bedingungen“ erfüllt sein müssen. Achten Sie darauf, dass Feldnamen und Werte mit den Dokumenten in Ihrer Sammlung übereinstimmen. Bei MongoDB wird zwischen Groß- und Kleinschreibung in Feldnamen unterschieden.

Mit $or mindestens eine Bedingung erfüllen

$or wählt Dokumente aus, auf die mindestens eine Klausel im Array zutrifft. Die Abfrage db.inventory.find({ $or: [{ quantity: { $lt: 51 } }, { price: 20 }] }) gibt beispielsweise ein Dokument zurück, wenn dessen Menge kleiner als 51 ist oder sein Preis 20 beträgt. Das Prädikat { price: 20 } prüft auf Gleichheit; es bedeutet nicht, dass der Preis kleiner als 20 ist. Verwenden Sie für einen Vergleich einen Operator wie $lt.

Hier sehen Sie eine kleine lokale Veranschaulichung der Regel „mindestens eine Bedingung“:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

inventory = [
    {"item": "notebook", "quantity": 30, "price": 12},
    {"item": "pen", "quantity": 80, "price": 20},
    {"item": "folder", "quantity": 80, "price": 8},
]
matched = [
    item["item"]
    for item in inventory
    if item["quantity"] < 51 or item["price"] == 20
]
print(matched)
['notebook', 'pen']

Dieses Python-Beispiel wendet die Auswahlregeln auf eine lokale Python-Liste an; es stellt keine Verbindung zu MongoDB her. Die Ausgabe führt das Notebook (Menge kleiner als 51) und den Stift (Preis gleich 20) auf. Die MongoDB-Shell-Abfrage oben wendet mit find() dieselbe Regel „mindestens eine Klausel“ auf das separat beschriebene Beispiel mit db.inventory an.

Mit $and jede Bedingung voraussetzen

$and wählt ein Dokument nur dann aus, wenn jede Klausel im Array zutrifft. Für die Beispiel-Sammlung db.inventory setzt db.inventory.find({ $and: [{ quantity: { $gte: 20 } }, { price: { $lt: 15 } }] }) sowohl eine Menge von mindestens 20 als auch einen Preis unter 15 voraus. Die Abfrage findet das Notebook und den Ordner: Bei beiden beträgt die Menge mindestens 20 und der Preis liegt unter 15.

Für unterschiedliche Felder lautet der gleichwertige Filter mit implizitem AND db.inventory.find({ quantity: { $gte: 20 }, price: { $lt: 15 } }). Wenn jedes Feld nur einmal vorkommt, ist diese kürzere Form vorzuziehen. Ein explizites $and ist nützlich, wenn die Abfrage mehrere Ausdrücke für dasselbe Feld kombinieren muss, etwa mit db.inventory.find({ $and: [{ price: { $gte: 10 } }, { price: { $lte: 20 } }] }). Außerdem macht es eine Gruppe von Bedingungen beim programmatischen Zusammensetzen von Filtern ausdrücklich sichtbar.

Verlassen Sie sich nicht darauf, dass die Reihenfolge der Klauseln in $and eine andere Klausel vor einem Fehler schützt. Abfrageausdrücke sind Bedingungen, die erfüllt sein müssen; eine garantierte Auswertung von links nach rechts mit vorzeitigem Abbruch gibt es nicht.

Einschränkungen bei Indizes und Operatoren

Indizes können für die Abfrageleistung relevant sein. Ob eine bestimmte Abfrage davon profitiert, hängt jedoch von der Sammlung, ihren Indizes und der Abfrage selbst ab. Berücksichtigen Sie die Felder und Prädikate Ihres Filters, wenn Sie die Leistung für Ihre eigene Arbeitslast bewerten. Dieser Artikel empfiehlt keinen bestimmten Index und keinen bestimmten Abfrageplan.

Achten Sie beim Kombinieren von Bedingungen auf die jeweilige Funktion der Operatoren: $or drückt Alternativen aus, $and verlangt, dass alle Klauseln zutreffen, und gewöhnliche Felder in einem Filter implizieren bereits AND. Mit dieser Unterscheidung vermeiden Sie logische Verknüpfungen, die die Bedeutung der Abfrage nicht verändern.

Für Gleichheitsalternativen in einem Feld $in wählen

Wenn mehrere Alternativen Gleichheitsprüfungen für dasselbe Feld sind, ist $in meist kürzer, als dieses Feld mehrfach in $or aufzuführen. Die Abfrage db.inventory.find({ price: { $in: [12, 20] } }) findet beispielsweise das Notebook und den Stift, deren Preise 12 beziehungsweise 20 betragen.

Verwenden Sie $or, wenn die Alternativen verschiedene Felder oder andere Prädikate als Gleichheit betreffen, etwa einen Mengenvergleich oder eine Preisbedingung. Nutzen Sie einen gewöhnlichen Filter mit mehreren Feldern, wenn alle darin enthaltenen Bedingungen zutreffen müssen. Welche Form passt, hängt von der gewünschten Logik ab: mindestens eine Klausel ($or), jede Klausel ($and, oft implizit) oder einer der aufgeführten Gleichheitswerte für ein Feld ($in).