07_SimpleMongoQuery

PDF-Dokumente

DateinameAktion
PDFFolie_SimpleMongoQuery.pdfÖffnen
PDFUebung_SimpleMongoQuery.pdfÖffnen

Videos

DateinameAktion
VIDEOVideo_Pizza_DAbspielen
VIDEOVideo_SimpleMongoQuery_DAbspielen

Lernmaterialien

Simple query

SELECT * FROM table

Die SQL-Abfrage

SELECT * FROM customer;

entspricht in MongoDB einfach:

db.customer.find({})

Falls du die Daten schön formatiert sehen willst:

db.customer.find({}).pretty()

Warum:
SELECT * bedeutet „alle Spalten“, und find({}) bedeutet „alle Dokumente der Collection“.
Die hochgeladene Datei zeigt, dass customer als Dokument-Collection mit verschachtelten Feldern wie adress und order aufgebaut ist.

Zum Vergleich:

  • SQL: SELECT * FROM customer;

  • MongoDB: db.customer.find({})

Falls du möchtest, kann ich dir auch gleich weitere SQL-Abfragen wie WHERE, JOIN, GROUP BY oder ORDER BY für diese MongoDB-Datenstruktur umschreiben.

SELECT Attribute FROM table

Wenn du in SQL nur bestimmte Attribute auswählst, zum Beispiel:

SELECT first_name, last_name, eMail FROM customer;

dann ist das in MongoDB:

db.customer.find(
  {},
  { first_name: 1, last_name: 1, eMail: 1 }
)

Mit schöner Ausgabe:

db.customer.find(
  {},
  { first_name: 1, last_name: 1, eMail: 1 }
).pretty()

Wichtig:

  • 1 bedeutet: Feld anzeigen

  • _id wird in MongoDB standardmäßig mit ausgegeben

Wenn du _id nicht sehen willst:

db.customer.find(
  {},
  { _id: 0, first_name: 1, last_name: 1, eMail: 1 }
)

Beispiel passend zu deiner Datenstruktur mit verschachtelten Attributen wie adress.city_name:

db.customer.find(
  {},
  { _id: 0, first_name: 1, "adress.city_name": 1 }
)

Also allgemein:

SELECT attribut1, attribut2 FROM customer;

wird zu

db.customer.find(
  {},
  { attribut1: 1, attribut2: 1 }
)

Ein Beispiel mit deinem product-Dokument wäre etwa product_type und prduct_name auswählen.

Wenn du willst, schreibe ich dir jetzt als Nächstes SELECT ... WHERE ... in MongoDB um.

unwind

Gerne.

$unwind wird in MongoDB verwendet, um ein Array aufzulösen.
Das bedeutet: Aus einem Dokument mit einer Liste werden mehrere Dokumente, jeweils eins pro Array-Element.

In deiner customer-Struktur ist order ein Array, und innerhalb jeder Bestellung ist product nochmal ein Array.

Ohne $unwind

Ein Kunde sieht vereinfacht so aus:

{
  first_name: "Anna",
  last_name: "Schmidt",
  order: [
    { order_date: "2025-01-05T18:30:00Z", ... },
    { order_date: "2025-01-22T18:30:00Z", ... },
    { order_date: "2025-02-08T18:30:00Z", ... }
  ]
}

Hier hat ein Dokument mehrere Bestellungen.

Mit $unwind: "$order"

Dann wird aus einem Kundendokument mit 3 Bestellungen 3 Dokumente:

db.customer.aggregate([
  { $unwind: "$order" }
])

Ergebnis vereinfacht:

{ first_name: "Anna", last_name: "Schmidt", order: { order_date: "2025-01-05T18:30:00Z", ... } }
{ first_name: "Anna", last_name: "Schmidt", order: { order_date: "2025-01-22T18:30:00Z", ... } }
{ first_name: "Anna", last_name: "Schmidt", order: { order_date: "2025-02-08T18:30:00Z", ... } }

Also:

  • vorher: 1 Kunde mit Liste von Bestellungen

  • nachher: 1 Zeile pro Bestellung

Warum braucht man das?

Weil MongoDB bei vielen Operationen mit einzelnen Elementen arbeiten muss, nicht mit einer ganzen Liste.

Zum Beispiel wenn du:

  • auf jede Bestellung einzeln zugreifen willst

  • nach Bestellungen filtern willst

  • mit Feldern in jeder Bestellung weiterarbeiten willst

  • später einen Join auf Produkte machen willst

Zweites $unwind in deiner Struktur

In jeder Bestellung gibt es zusätzlich das Array order.product.

Beispiel:

{
  order_date: "2025-01-05T18:30:00Z",
  product: [
    { product_id: "000...005", product_name: "Margherita Pizza" },
    { product_id: "000...007", product_name: "Garlic Bread" },
    { product_id: "000...009", product_name: "Cola 0.5L" }
  ]
}

Wenn du auch dieses Array auflösen willst:

db.customer.aggregate([
  { $unwind: "$order" },
  { $unwind: "$order.product" }
])

Dann erhältst du:

  • 1 Dokument pro Kunde

  • pro Bestellung

  • pro Produkt

Also z. B. für Anna mehrere Zeilen, jeweils eine pro bestelltem Produkt.

Anschaulich

$unwind ist ähnlich wie:

  • eine Liste „aufklappen“

  • jede Listenzeile einzeln machen

  • aus 1:n wieder einzelne Datensätze erzeugen

Warum vor dem INNER JOIN?

Beim Join wollten wir order.product.product_id mit product._id verbinden.

Das Problem:
order ist ein Array und order.product auch ein Array.
Darum muss man erst mit $unwind auf ein konkretes Produkt pro Dokument kommen.

Erst danach ist ein Join mit $lookup sauber möglich.

SELECT * FROM table1 inner join table2

Ein INNER JOIN wird in MongoDB normalerweise mit $lookup umgesetzt.

Wichtig: MongoDB kennt nicht direkt den SQL-Befehl INNER JOIN wie relationale Datenbanken. Das Gegenstück ist meist eine Aggregation mit $lookup.

SQL-Beispiel:

SELECT *
FROM customer c
INNER JOIN product p
  ON c.product_id = p._id;

In deiner Datenstruktur ist der Join etwas spezieller, weil:

  • customer eine verschachtelte Liste order

  • darin wieder eine Liste product

  • und dort das Feld product_id

enthält.
Die Produktdaten liegen separat in product mit _id.

Dafür brauchst du in MongoDB:

db.customer.aggregate([
  { $unwind: "$order" },
  { $unwind: "$order.product" },
  {
    $lookup: {
      from: "product",
      localField: "order.product.product_id",
      foreignField: "_id",
      as: "product_details"
    }
  },
  { $unwind: "$product_details" }
])

Warum das ein INNER JOIN ist:

  • $lookup verbindet customer mit product

  • das letzte $unwind: "$product_details" sorgt dafür, dass nur Treffer bleiben

  • damit verhält es sich wie ein INNER JOIN

Ein sinnvolleres Ergebnis, also nur ausgewählte Felder:

db.customer.aggregate([
  { $unwind: "$order" },
  { $unwind: "$order.product" },
  {
    $lookup: {
      from: "product",
      localField: "order.product.product_id",
      foreignField: "_id",
      as: "product_details"
    }
  },
  { $unwind: "$product_details" },
  {
    $project: {
      _id: 0,
      first_name: 1,
      last_name: 1,
      "order.order_date": 1,
      "order.product.product_id": 1,
      "order.product.product_name": 1,
      "product_details.product_type": 1,
      "product_details.product_decription": 1
    }
  }
])

SQL-Logik dazu wäre ungefähr:

SELECT c.first_name, c.last_name, op.product_id, p.product_type, p.product_decription
FROM customer c
INNER JOIN order_product op ON ...
INNER JOIN product p ON op.product_id = p._id;

Merksatz:

  • SQL INNER JOIN

  • in MongoDB meist $lookup + $unwind

SELECT GROUP BY

Gerne.
Ein SELECT ... GROUP BY wird in MongoDB mit aggregate() und $group umgesetzt.

SQL-Beispiel

SELECT city_name, COUNT(*) 
FROM customer
GROUP BY city_name;

MongoDB

Da city_name bei dir in adress.city_name steckt, ist die passende MongoDB-Abfrage:

db.customer.aggregate([
  {
    $group: {
      _id: "$adress.city_name",
      anzahl_kunden: { $sum: 1 }
    }
  }
])

Die Kundendaten enthalten das verschachtelte Feld adress.city_name, daher wird genau dieses Feld im $group verwendet.

Erklärung

  • aggregate([...]) startet die Aggregation

  • $group entspricht dem SQL-GROUP BY

  • _id ist das Gruppierungsfeld

  • { $sum: 1 } zählt die Dokumente pro Gruppe

Mit schönerer Ausgabe

Wenn du statt _id lieber einen sprechenden Feldnamen möchtest:

db.customer.aggregate([
  {
    $group: {
      _id: "$adress.city_name",
      anzahl_kunden: { $sum: 1 }
    }
  },
  {
    $project: {
      _id: 0,
      city_name: "$_id",
      anzahl_kunden: 1
    }
  }
])

Weiteres Beispiel: Produkte nach Typ gruppieren

Aus deiner product-Collection kann man auch nach product_type gruppieren.

SQL

SELECT product_type, COUNT(*)
FROM product
GROUP BY product_type;

MongoDB

db.product.aggregate([
  {
    $group: {
      _id: "$product_type",
      anzahl: { $sum: 1 }
    }
  }
])

Mit SUM statt COUNT

SQL

SELECT restaurant_name, SUM(number_of_pieces)
FROM customer
GROUP BY restaurant_name;

Da restaurant_name und number_of_pieces in deinem Array order.product liegen, muss man vorher unwind verwenden.

MongoDB

db.customer.aggregate([
  { $unwind: "$order" },
  { $unwind: "$order.product" },
  {
    $group: {
      _id: "$order.product.restaurant_name",
      gesamt_menge: { $sum: "$order.product.number_of_pieces" }
    }
  }
])

Merksatz

  • SQL GROUP BY → MongoDB $group

  • SQL COUNT(*) → MongoDB { $sum: 1 }

  • SQL SUM(feld) → MongoDB { $sum: "$feld" }

Allgemeines Muster

SELECT feld, COUNT(*)
FROM tabelle
GROUP BY feld;

wird zu

db.tabelle.aggregate([
  {
    $group: {
      _id: "$feld",
      anzahl: { $sum: 1 }
    }
  }
])