MongoDB Arrays abfragen

MongoDBBeginner
Jetzt üben

Einführung

In diesem Lab lernen Sie, wie Sie Arrays in MongoDB effektiv abfragen. Arrays sind eine grundlegende Datenstruktur in MongoDB, die es Ihnen ermöglicht, Listen von Werten in einem einzigen Dokumentfeld zu speichern. Dieses Lab führt Sie durch die wesentlichen Techniken für die Arbeit mit Array-Daten, von der einfachen Elementübereinstimmung bis hin zu komplexeren Abfragen mit spezialisierten Operatoren. Sie lernen, wie Sie Dokumente basierend auf Array-Inhalt, Größe und Elementposition finden, was entscheidende Fähigkeiten für jeden Entwickler sind, der mit MongoDB arbeitet.

Erste Schritte und grundlegende Array-Übereinstimmung

In diesem ersten Schritt verbinden Sie sich mit dem MongoDB-Server, erstellen eine Datenbank und fügen einige Beispieldaten ein. Anschließend führen Sie grundlegende Abfragen durch, um Dokumente durch Abgleich von Elementen innerhalb eines Arrays zu finden.

Öffnen Sie zuerst die MongoDB Shell (mongosh), um mit Ihrer Datenbank zu interagieren. Dieser Befehl verbindet Sie mit der laufenden MongoDB-Instanz.

mongosh

Sobald Sie sich in der Shell befinden, sehen Sie eine test> Eingabeaufforderung. Wechseln wir zu einer neuen Datenbank namens arraylab. Der Befehl use erstellt die Datenbank, falls sie noch nicht existiert, und wechselt den aktuellen Kontext dorthin.

use arraylab

Nun fügen wir einige Dokumente in eine neue Collection namens products ein. Jedes Dokument repräsentiert ein Produkt und enthält zwei Array-Felder: tags und colors. Kopieren Sie den folgenden Befehl und fügen Sie ihn in Ihre Shell ein:

db.products.insertMany([
  {
    name: "Laptop",
    tags: ["electronics", "computer", "work"],
    colors: ["silver", "black", "blue"]
  },
  {
    name: "Smartphone",
    tags: ["electronics", "mobile", "communication"],
    colors: ["red", "blue", "green"]
  },
  {
    name: "Headphones",
    tags: ["electronics", "audio", "music"],
    colors: ["black", "white"]
  }
]);

Um ein Dokument zu finden, das ein bestimmtes Element in einem Array enthält, können Sie direkt nach diesem Wert abfragen. Diese Abfrage findet alle Produkte, die den Tag "mobile" haben.

db.products.find({ tags: "mobile" });

Beispielausgabe:

[
  {
    _id: ObjectId("..."),
    name: 'Smartphone',
    tags: [ 'electronics', 'mobile', 'communication' ],
    colors: [ 'red', 'blue', 'green' ]
  }
]

Sie können auch Dokumente finden, bei denen das Array einer exakten Elementsequenz entspricht. Diese Abfrage findet das Produkt, dessen tags-Array genau ["electronics", "computer", "work"] in dieser spezifischen Reihenfolge ist.

db.products.find({ tags: ["electronics", "computer", "work"] });

Beispielausgabe:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  }
]

Sie können für die nächsten Schritte in der mongosh-Shell bleiben. Um die Shell jederzeit zu verlassen, geben Sie exit ein und drücken Sie Enter.

Array-Abfrageoperatoren $all und $in verwenden

Einfache Abgleiche sind nützlich, aber MongoDB bietet leistungsstarke Operatoren für komplexere Array-Abfragen. In diesem Schritt lernen Sie, $all zu verwenden, um mehrere Elemente unabhängig von ihrer Reihenfolge abzugleichen, und $in, um eines von mehreren Elementen abzugleichen.

Wir werden weiterhin die products-Collection aus dem vorherigen Schritt verwenden.

Der $all-Operator wählt Dokumente aus, bei denen das Array-Feld alle angegebenen Elemente enthält. Die Reihenfolge der Elemente in der Abfrage spielt keine Rolle. Suchen wir nach Produkten, die sowohl in "blue" als auch in "silver" erhältlich sind.

db.products.find({ colors: { $all: ["blue", "silver"] } });

Beispielausgabe:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  }
]

Der $in-Operator wählt Dokumente aus, bei denen das Array-Feld mindestens einen der angegebenen Werte enthält. Er fungiert als "ODER"-Bedingung für Array-Elemente. Suchen wir nach Produkten, die entweder den Tag "music" oder den Tag "work" haben.

db.products.find({ tags: { $in: ["music", "work"] } });

Beispielausgabe:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Headphones',
    tags: [ 'electronics', 'audio', 'music' ],
    colors: [ 'black', 'white' ]
  }
]

Diese Operatoren bieten deutlich mehr Flexibilität bei der Suche nach Dokumenten basierend auf dem Inhalt ihrer Arrays.

Abfragen nach Array-Größe und Position

Manchmal sind die Anzahl der Elemente in einem Array oder die Position eines bestimmten Elements wichtig. Dieser Schritt behandelt, wie man basierend auf der Array-Größe mit dem $size-Operator und nach Elementposition mit Punktnotation abfragt.

Der $size-Operator wählt Dokumente aus, die ein Array mit einer bestimmten Anzahl von Elementen haben. Suchen wir nach Produkten, die genau zwei Farben verfügbar haben.

db.products.find({ colors: { $size: 2 } });

Beispielausgabe:

[
  {
    _id: ObjectId("..."),
    name: 'Headphones',
    tags: [ 'electronics', 'audio', 'music' ],
    colors: [ 'black', 'white' ]
  }
]

Um nach einem Element an einer bestimmten Position (Index) in einem Array abzufragen, verwenden Sie die Punktnotation im Format "fieldName.index". Denken Sie daran, dass Array-Indizes nullbasiert sind, sodass das erste Element am Index 0 liegt. Diese Abfrage findet alle Produkte, bei denen das erste Element im tags-Array "electronics" ist.

db.products.find({ "tags.0": "electronics" });

Beispielausgabe:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Smartphone',
    tags: [ 'electronics', 'mobile', 'communication' ],
    colors: [ 'red', 'blue', 'green' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Headphones',
    tags: [ 'electronics', 'audio', 'music' ],
    colors: [ 'black', 'white' ]
  }
]

Suchen wir nun nach einem Produkt, bei dem die zweite Farbe (Index 1) "black" ist.

db.products.find({ "colors.1": "black" });

Beispielausgabe:

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  }
]

Arrays von eingebetteten Dokumenten abfragen

Ein gängiges und leistungsstarkes Muster in MongoDB ist die Verwendung von Arrays, die andere Dokumente enthalten. Diese werden als eingebettete oder verschachtelte Dokumente bezeichnet. Die Abfrage dieser erfordert einen speziellen Operator, $elemMatch, um sicherzustellen, dass alle Bedingungen auf dasselbe Array-Element angewendet werden.

Zuerst fügen wir einige neue Produkte hinzu, die ein specs-Array haben. Jedes Element im specs-Array ist ein Dokument mit den Feldern ram, storage und price.

db.products.insertMany([
  {
    name: "Gaming Laptop",
    tags: ["electronics", "computer", "gaming"],
    specs: [
      { ram: 16, storage: 512, price: 1200 },
      { ram: 32, storage: 1024, price: 2000 }
    ]
  },
  {
    name: "Office Laptop",
    tags: ["electronics", "computer", "work"],
    specs: [
      { ram: 8, storage: 256, price: 600 },
      { ram: 16, storage: 512, price: 800 }
    ]
  }
]);

Angenommen, wir möchten nun einen Laptop finden, der eine Konfiguration mit mindestens 16 GB RAM und einem Preis unter 1000 $ hat. Eine einfache Abfrage mag korrekt erscheinen, kann aber zu falschen Ergebnissen führen. Zum Beispiel würde db.products.find({ "specs.ram": { $gte: 16 }, "specs.price": { $lt: 1000 } }) ein Dokument abgleichen, wenn ein eingebettetes Dokument genügend RAM hat und ein anderes eine ausreichend niedrige Preisangabe hat.

Um sicherzustellen, dass ein einzelnes eingebettetes Dokument im Array alle Bedingungen erfüllt, müssen Sie den $elemMatch-Operator verwenden.

db.products.find({
  specs: {
    $elemMatch: { ram: { $gte: 16 }, price: { $lt: 1000 } }
  }
});

Diese Abfrage findet korrekt nur den "Office Laptop", da dieser ein Spezifikationselement { ram: 16, storage: 512, price: 800 } hat, das beide Bedingungen gleichzeitig erfüllt.

Beispielausgabe:

[
  {
    _id: ObjectId("..."),
    name: 'Office Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    specs: [
      { ram: 8, storage: 256, price: 600 },
      { ram: 16, storage: 512, price: 800 }
    ]
  }
]

Array-Felder projizieren

Oft benötigen Sie nicht das gesamte Dokument, das aus einer Abfrage zurückgegeben wird. Die Projektion ermöglicht es Ihnen, anzugeben, welche Felder ein- oder ausgeschlossen werden sollen. Für Arrays bietet MongoDB spezielle Projektionsoperatoren wie $slice, um zu steuern, welche Array-Elemente zurückgegeben werden.

Der $slice-Projektionsoperator gibt eine Teilmenge eines Arrays zurück. Sie können eine positive Zahl angeben, um die ersten N Elemente zu erhalten, oder eine negative Zahl, um die letzten N Elemente zu erhalten.

Rufen wir alle Produkte ab, geben aber für jedes Produkt nur den name und die ersten beiden tags zurück. Das erste Argument von find, {}, ist ein leeres Abfragedokument, das allen Dokumenten entspricht. Das zweite Argument ist das Projektionsdokument. Wir verwenden _id: 0, um das Standard-_id-Feld auszuschließen.

db.products.find({}, { name: 1, tags: { $slice: 2 }, _id: 0 });

Beispielausgabe:

[
  { "name": "Laptop", "tags": ["electronics", "computer"] },
  { "name": "Smartphone", "tags": ["electronics", "mobile"] },
  { "name": "Headphones", "tags": ["electronics", "audio"] },
  { "name": "Gaming Laptop", "tags": ["electronics", "computer"] },
  { "name": "Office Laptop", "tags": ["electronics", "computer"] }
]

Ein weiterer nützlicher Projektionsoperator ist der positionale $-Operator. Wenn Sie ein Array abfragen, stellt dieser Operator sicher, dass nur das erste Element, das der Abfragebedingung entsprach, im projizierten Array-Feld zurückgegeben wird.

Suchen wir nach Produkten mit dem Tag "mobile" und geben nur den name und diesen spezifischen übereinstimmenden Tag aus dem tags-Array zurück.

db.products.find({ tags: "mobile" }, { name: 1, "tags.$": 1, _id: 0 });

Beispielausgabe:

[{ "name": "Smartphone", "tags": ["mobile"] }]

Dies ist sehr effizient, um nur die relevanten Teile eines großen Arrays abzurufen, ohne das gesamte Array in Ihrer Anwendung verarbeiten zu müssen.

Zusammenfassung

In diesem Lab haben Sie die grundlegenden Techniken für die Abfrage von Arrays in MongoDB kennengelernt. Sie haben mit grundlegenden Elementübereinstimmungen begonnen und sind dann zu leistungsstarken Array-Operatoren wie $all, $in und $size übergegangen. Sie haben auch untersucht, wie man nach der Position eines Elements abfragt und wie man Arrays von eingebetteten Dokumenten mit $elemMatch korrekt abfragt. Schließlich haben Sie gelernt, wie Sie die Ausgabe Ihrer Abfragen durch Projektion spezifischer Array-Elemente mit $slice und dem positionalen $-Operator gestalten können. Diese Fähigkeiten sind unerlässlich für die effektive Verwaltung und Abfrage von Daten aus komplexen Dokumentstrukturen in MongoDB.