Der MongoDB "Find" Befehl Finden von Dokumenten in MongoDB

Finden von Dokumenten anhand deren Attribut Werte

Wenn JSON Dokumente in eine "MongoDB Collection" eingefügt werden, so bekommen diese automatisch ein '_id' Feld von System zugewiesen. Ein Dokument anhand seiner id zu finden ist recht einfach. Das folgende Beispiel zeigt wie ein Dokument mit der _id=568c28fffc4be30d44d0398e in der Collection “products” gefunden wird:

$ mongo localhost:27017/[database-name]
> db.products.find({"_id": ObjectId("568c28fffc4be30d44d0398e")})
{
  "_id" : ObjectId("568c28fffc4be30d44d0398e"),
  "product_number" : 19,
  "supplier_id" : ObjectId("568c28fffc4be30d44d0397a"),
  "title" : "Big Data: Principles and Best Practices of Scalable Realtime Data Systems",
  "description" : "A book written by Nathan Marz and James Warren.",
  "price" : 36.00
}

Wenn mittels find Befehl ein Dokument anhand des _id Attribut gesucht wird, so wird das Ergebnis entweder genau ein Dokument oder gar kein Dokument umfassen.

Weiterhin ist es möglich Dokumente anhand anderer Attribute als dem ID Attribut wieder zu finden. Um beim obigen Beispiel zu bleiben, zeigt der folgende Code block, wie alle Dokument aus der “products” Collection mit einem bestimmten Titel gesucht werden:

$ mongo localhost:27017/[database-name]
> db.products.find({"title": "Big Data: Principles and Best Practices of Scalable Realtime Data Systems"})

Oft sind JSON Dokumente ineinander verschachtelt. Das bedeutet, dass ein Key auf einen weiteren Key-Value Hash verweist. Auch in diesem Fall bietet MongoDB die Möglichkeit Dokumente anhand von Werten zu suchen, welche in einer verschachtelten JSON- Struktur hinterlegt sind:

{
  "_id" : ObjectId("568c28fffc4be30d44d039aa"),
  "firstname" : "Max",
  "lastname" : "Mustermann",
  "email" : "m.mustermann@example.com",
  "password" : "d9729feb74992cc3482b350163a1a010,
  "last_login" : "2015-01-07",
  "note" : "Always pays in time, very good customer!",
  "address" :
  {
    "country" : "Germany",
    "street" : "Beispielstrasse 64",
    "zip" : "62717"
  }
}

Obiges JSON Dokument zeigt wie ein verschachteltes JSON aussehen kann. In diesem Beispiel sind die Felder der Adresse (Country, Street, Zip) in einer eigenen Key- Value Map beschrieben. Folgendes Kommando findet alle Kunden die in Deutschland ansässig sind:

> db.customers.find({"address.country": "Germany"})

Verknüpfen von Bedingungen

Oft ist es erforderlich Dokumente anhand von mehreren Feldern zu suchen. Zum Beispiel um alle Kunden aus Deutschland zu finden welche sich heute bereits eingeloggt haben. Dazu ist es notwendig auf die Werte der Felder "last_login" und "address.country" zuzugreifen und mit einer Bedingung zu verknüpfen. Die Verknüpfung welche in diesem Beispiel genutzt werden muss, ist die und- Verknüpfung, da wir Dokumente suchen, welche beide Eigenschaften erfüllen sollen:

> db.customers.find({
  $and: [
    {"address.country": "Germany"},
    {"last_login": "2018-11-16"}
  ]
})

Im nächsten Beispiel sollen alle Kunden aus der Europäischen Union gefunden werden. Dies heißt der Kunde muss aus einem Land der Europäischen Union kommen:

> db.customers.find({
  $or: [
    {"address.country": "Austria"}, {"address.country": "Belgium"},
    {"address.country": "Bulgaria"}, {"address.country": "Croatia"},
    {"address.country": "Cyprus"}, {"address.country": "Czech Republic"},
    {"address.country": "Denmark"}, {"address.country": "Estonia"},
    {"address.country": "Finland"}, {"address.country": "France"},
    {"address.country": "Germany"}, {"address.country": "Greece"},
    {"address.country": "Hungary"}, {"address.country": "Ireland"},
    {"address.country": "Italy"}, {"address.country": "Latvia"},
    {"address.country": "Lithuania"}, {"address.country": "Luxembourg"},
    {"address.country": "Malta"}, {"address.country": "The Netherlands"},
    {"address.country": "Poland"}, {"address.country": "Portugal"},
    {"address.country": "Romania"}, {"address.country": "Slovakia"},
    {"address.country": "Slovenia"}, {"address.country": "Spain"},
    {"address.country": "Sweden"}, {"address.country": "United Kingdom"}
  ]
})

Nun soll gezeigt werden wie die beiden Operatoren “$and” und “$or” verknüpft werden können. Dazu sollen alle Kunden gefunden werden welche sich in den letzten drei Tagen eingeloggt haben und aus Spanien oder Frankreich kommen:

> db.customers.find({
  $and: [
    {
      $or: [{"last_login": "2018-11-16"},
            {"last_login": "2018-11-15"},
            {"last_login": "2018-11-14"}]
    },
    {
      $or: [{"address.country": "Spain"},
            {"address.country": "France"}]
    }
  ]
})

Finden von Dokumente mit Query Selectors

In obigen Beispielen wurden Dokumente immer anhand von exakten Werten gesucht. Also beispielsweise Dokumente bei denen das Feld “last_login” ganz genau dem Wert “2018-11-16” entspricht. Glücklicherweise bietet MongoDB hier noch mehr Möglichkeiten. So kann nach Produkte (bzw. nach Dokumenten welche Produkte repräsentieren) gesuchten werden deren Preis höher ist als ein bestimmter Wert. Ein weiteres Beispiel: Es kann nach Kunden gesucht werden deren Kommentar das Wort “bad” enthält.

Aber eins nach dem anderen, hier zuerst eine Tabelle mit verfügbaren Operatoren von denen wir einige weiter untern verwenden werden:

Operator Beschreibung
$eq Findet alle Dokumente bei denen der angebende Wert exakt mit dem Wert in dem zu prüfenden Feld der JSON- Dokumente übereinstimmt.
$gt Findet alle Dokumente bei denen der angebende Wert größer ist als der Wert in dem zu prüfenden Feld der JSON- Dokumente.
$gte Findet alle Dokumente bei denen der angebende Wert größer oder gleich ist als der Wert in dem zu prüfenden Feld der JSON- Dokumente.
$lt Findet alle Dokumente bei denen der angebende Wert kleiner ist als der Wert in dem zu prüfenden Feld der JSON- Dokumente.
$lte Findet alle Dokumente bei denen der angebende Wert kleiner oder gleich ist als der Wert in dem zu prüfenden Feld der JSON- Dokumente.
$ne Findet alle Dokumente bei denen sich der angebende Wert von dem zu prüfenden Feld JSON- Dokumente unterscheidet.
$in Findet alle Dokumente bei denen sich das zu prüfenden Feld der JSON- Dokumente in einer angebenden Liste mit möglichen Werten befindet.
$nin Findet alle Dokumente bei denen sich das zu prüfenden Feld der JSON- Dokumente NICHT in einer angebenden Liste mit Werten befindet.
Angelehnt an: docs.mongodb.org

Wie weiter oben bereits angekündigt ist es möglich einige der Abfragen kürzer zu formulieren. Mit den gerade eingeführten Operatoren ist dies nun möglich. So kann die Abfrage bei der wir alle Kunden suchen (welche sich in den letzten drei Tagen eingeloggt haben und aus Spanien oder Frankreich kommen) wie folgt umgeschrieben werden:

> db.customers.find({
  $and: [
    { "last_login": { $in: ["2018-11-16", "2018-11-15", "2018-11-14"] }},
    { "address.country": { $in: ["Spain", "French"] }},
  ]
})

Der $gte oder $gt Operator erlaubt es uns die letzte Anfrage noch kürzer zu formulieren. Der $gt ermöglicht es uns alle Kunden zu finden deren “last_login” Feld einen Wert größer als der angebende Wert enthält. Dabei spielt es keine Rolle ob zwei Numerische Werte oder zwei Zeichenketten verglichen werden. In diesem Beispiel sind die Datumsfelder als Zeichenkette kodiert und werden somit lexikografisch verglichen. Sprich nach der alphabetischen Ordnung. Die Kodierung des Datums ist so gewählt, dass die alphabetische Ordnung mit der tatsächlichen Reihenfolge der Zeitpunkte übereinstimmt (Die Zeichenkette "2015-12-24" steht sowohl lexikographisch als auch von dem zu repräsentierten Zeitpunkt her vor der Zeichenkette "2016-12-24").

> db.customers.find({
  $and: [
    { "last_login": { $gte: "2018-11-14" }},
    { "address.country": { $in: ["Spain", "French"] }},
  ]
})

Das Gegenteil der $gte/$gt Operatoren sind die $lte/$lt Operatoren. Der $lt Operator soll im nächsten Beispiel eingesetzt werden um all Kunden zu finden welche sich NICHT in den letzten drei Tagen eingeloggt haben:

> db.customers.find({
  "last_login": { $lt: "2018-11-14" }
})

Die folgende Abfrage zeigt wie der “$nin” Operator dazu genutzt wird alle Kunden zu finden die NICHT aus Spanien oder Frankreich sind:

> db.customers.find({
  "address.country": { $nin: ["Spain", "French"] }
})