MongoDB Academy · Lektion

$lookup: Collections in der Pipeline verknüpfen

Sie führen mit $lookup Left-Outer-Joins zwischen Collections aus und verstehen die Performance-Auswirkungen von Joins über mehrere Collections hinweg.

Lektion 1 von 413 Schritte

$lookup: Collections in der Pipeline verknüpfen ist eine kostenlose MongoDB Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des MongoDB Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.

Warum es $lookup gibt

MongoDB ist auf das Einbetten zusammengehöriger Daten ausgelegt. Manchmal müssen Daten jedoch in getrennten Collections gespeichert werden – insbesondere bei Viele-zu-viele- oder Eins-zu-viele-Beziehungen, bei denen das Einbetten zu unbeschränktem Dokumentwachstum führen würde. Die Phase $lookup führt einen Left Outer Join zwischen der aktuellen Collection (der „linken“ Seite) und einer anderen Collection (der „rechten“ Seite) aus. So können Sie zusammengehörige Daten serverseitig in einer einzigen Aggregationspipeline zusammenführen.

Grundlegende $lookup-Syntax

Das grundlegende $lookup besitzt vier erforderliche Felder: from (die zu verknüpfende Collection), localField (das Feld im Eingabedokument), foreignField (das Feld in der verknüpften Collection) und as (der Name des Array-Felds, das der Ausgabe hinzugefügt wird). Das Ergebnis ist ein Array, da ein Dokument mehreren Dokumenten in der verknüpften Collection entsprechen kann.

// Join orders with their product details
db.orders.aggregate([
  { $lookup: {
    from: 'products',          // collection to join
    localField: 'productId',   // field in orders
    foreignField: '_id',       // field in products
    as: 'productDetails'       // output array field name
  }}
]);
// Each order now has a 'productDetails' array with matching products

Das verknüpfte Array auflösen

Da $lookup im Feld as immer ein Array erzeugt, müssen Sie dieses häufig abflachen, um direkt auf Unterfelder zugreifen zu können. Wenn Sie wissen, dass die Verknüpfung eins zu eins ist (z. B. über eine eindeutige _id), verwenden Sie direkt nach $lookup $unwind, um das Array in ein einzelnes eingebettetes Objekt umzuwandeln. Beachten Sie, dass $unwind Dokumente ohne Treffer (leere Arrays) entfernt.

db.orders.aggregate([
  { $lookup: {
    from: 'products',
    localField: 'productId',
    foreignField: '_id',
    as: 'product'
  }},
  // Flatten: productDetails array -> productDetails object
  { $unwind: '$product' },
  // Now access product fields directly:
  { $project: { orderId: '$_id', amount: 1, 'product.name': 1, 'product.price': 1 } }
]);

$lookup als Left Outer Join

$lookup führt einen Left Outer Join aus: Jedes Dokument aus der linken (Eingabe-)Collection wird in die Ausgabe aufgenommen, selbst wenn es in der rechten (fremden) Collection keine passenden Dokumente gibt. In diesem Fall wird das Feld as auf ein leeres Array gesetzt. Das unterscheidet sich von einem Inner Join, bei dem nicht passende Dokumente der linken Seite ausgeschlossen würden. Um nicht passende Dokumente herauszufiltern, fügen Sie nach $lookup ein $match hinzu.

db.orders.aggregate([
  { $lookup: {
    from: 'products',
    localField: 'productId',
    foreignField: '_id',
    as: 'product'
  }},
  // Simulate inner join: exclude orders with no matching product
  { $match: { product: { $ne: [] } } },
  // Or equivalently:
  { $match: { 'product.0': { $exists: true } } }
]);

Pipeline-$lookup für komplexe Verknüpfungen

Die erweiterte Form von $lookup verwendet anstelle eines einfachen Feldvergleichs eine pipeline-Option. Dadurch können beliebige Phasen in der verknüpften Collection ausgeführt werden, bevor die Verknüpfung erfolgt. Innerhalb der verknüpften Pipeline können Sie mithilfe von $$let-Variablen, die Werte aus dem übergeordneten Dokument übergeben, filtern, Projektionen erstellen und Berechnungen durchführen. So werden komplexe bedingte Verknüpfungen und Verknüpfungen mit Ungleichheitsbedingungen möglich.

// Join only active discounts for each product
db.products.aggregate([
  { $lookup: {
    from: 'discounts',
    let: { productId: '$_id', price: '$price' },  // pass parent fields
    pipeline: [
      { $match: {
        $expr: {
          $and: [
            { $eq: ['$productId', '$$productId'] },  // use $$var
            { $eq: ['$active', true] }
          ]
        }
      }},
      { $project: { amount: 1, expiresAt: 1 } }
    ],
    as: 'activeDiscounts'
  }}
]);

Self-Join mit $lookup

Sie können $lookup verwenden, um eine Collection mit sich selbst zu verknüpfen – beispielsweise, um den Vorgesetzten eines Benutzers zu finden, indem Sie die ID des Vorgesetzten in derselben Users-Collection nachschlagen. Setzen Sie from auf denselben Collection-Namen wie bei der Eingabe-Collection. Self-Joins sind für hierarchische Daten oder Dokumente nützlich, die auf ein anderes Dokument in derselben Collection verweisen.

// Self-join: attach manager details to each employee
db.employees.aggregate([
  { $lookup: {
    from: 'employees',     // same collection
    localField: 'managerId',
    foreignField: '_id',
    as: 'manager'
  }},
  { $unwind: { path: '$manager', preserveNullAndEmptyArrays: true } },
  { $project: {
    name: 1,
    department: 1,
    'manager.name': 1
  }}
]);

Performanceaspekte bei $lookup

$lookup kann aufwendig sein, wenn die verknüpfte Collection groß und nicht indiziert ist. MongoDB erstellt während der Verknüpfung einen temporären Index für das Fremdfeld, sofern noch keiner vorhanden ist; dieser Index bleibt jedoch nicht dauerhaft bestehen. Für wiederholte $lookup-Operationen auf demselben Feld sollten Sie einen dauerhaften Index für das Feld der fremden Collection erstellen, um diesen Aufwand bei jeder Abfrage zu vermeiden.

// Ensure foreignField is indexed in the joined collection
// 'products' is the joined collection, '_id' is always indexed
// But for custom fields, index explicitly:
db.discounts.createIndex({ productId: 1, active: 1 });

// Now this $lookup is fast because productId is indexed
db.products.aggregate([{
  $lookup: {
    from: 'discounts',
    localField: '_id',
    foreignField: 'productId',  // indexed!
    as: 'discounts'
  }
}]);

Mehrere $lookup-Phasen

Sie können mehrere $lookup-Phasen verketten, um mehr als zwei Collections in einer einzigen Pipeline zu verknüpfen. Jede $lookup-Phase fügt dem Dokumentdatenstrom ein neues Array-Feld hinzu. Bedenken Sie, dass jede zusätzliche Verknüpfung das Datenvolumen und die Rechenkosten vervielfacht – vermeiden Sie es, mehr als 2–3 große Collections in einer einzigen Pipeline zu verknüpfen. Wenn Sie viele Verknüpfungen benötigen, prüfen Sie erneut, ob das Einbetten einiger Daten das Schema vereinfachen würde.

db.orders.aggregate([
  // Join 1: product details
  { $lookup: { from: 'products', localField: 'productId', foreignField: '_id', as: 'product' } },
  { $unwind: '$product' },

  // Join 2: customer details
  { $lookup: { from: 'customers', localField: 'customerId', foreignField: '_id', as: 'customer' } },
  { $unwind: '$customer' },

  { $project: {
    _id: 1, amount: 1,
    'product.name': 1,
    'customer.email': 1
  }}
]);

$lookup-Daten mit einer Pipeline-Teilprojektion reduzieren

Fügen Sie in der Pipeline-Form von $lookup innerhalb der Verknüpfungs-pipeline eine Phase $project ein, um aus der verknüpften Collection nur die benötigten Felder abzurufen. Dadurch reduzieren Sie die aus der verknüpften Collection übertragenen Daten sowie den Speicherbedarf des Verknüpfungsergebnisses. Verknüpfen Sie niemals ganze große Dokumente, wenn Sie daraus nur zwei oder drei Felder benötigen.

db.orders.aggregate([{
  $lookup: {
    from: 'products',
    let: { pid: '$productId' },
    pipeline: [
      { $match: { $expr: { $eq: ['$_id', '$$pid'] } } },
      // Only fetch name and imageUrl, not the full product document
      { $project: { _id: 0, name: 1, imageUrl: 1, price: 1 } }
    ],
    as: 'product'
  }
}]);

$lookup oder Einbetten: der Kompromiss

Jedes $lookup ist ein Kompromiss: Es bietet Ihnen Flexibilität zum Zeitpunkt der Abfrage, verursacht aber im Vergleich zum Lesen eingebetteter Daten in einem einzigen Dokument zusätzliche Latenz. Verwenden Sie $lookup, wenn sich die verknüpften Daten häufig ändern und Sie eine einzige Quelle der Wahrheit benötigen, die Beziehung Viele-zu-viele ist oder das Einbetten zu unbeschränktem Dokumentwachstum führen würde. Verwenden Sie das Einbetten, wenn Lesevorgänge häufig sind und sich die zusammengehörigen Daten selten unabhängig ändern.

// When to embed (avoid $lookup):
// - User profile with 2-3 addresses (bounded, read often together)
// { user: { name, email, addresses: [...] } }

// When to $lookup (use references):
// - Orders referencing products (products change, shared by many orders)
// { order: { productId: ObjectId(...), qty: 2 } }
// -> $lookup products on read

Kompakte Verknüpfung mit $lookup auf Arrays

$lookup unterstützt auch den Fall, dass localField ein Array von IDs ist. MongoDB führt automatisch eine Verknüpfung mit mehreren Werten durch: Für jedes Element im localField-Array sucht MongoDB das passende Dokument in der fremden Collection und sammelt alle Ergebnisse. So lässt sich das tagIds-Array eines Beitrags in einem Schritt mit einer tags-Collection verknüpfen.

// Post document: { title: '...', tagIds: [ObjectId1, ObjectId2] }
// Join all tag documents for a post's tagIds array:
db.posts.aggregate([{
  $lookup: {
    from: 'tags',
    localField: 'tagIds',  // this is an array!
    foreignField: '_id',
    as: 'tags'
  }
}]);
// tags array in output contains one doc per ObjectId in tagIds

Kurztest

Testen Sie Ihr Verständnis von $lookup in der Aggregationspipeline.

Lektionszusammenfassung

In dieser Lektion haben Sie gelernt: $lookup führt zwischen zwei Collections anhand übereinstimmender Feldwerte einen Left Outer Join durch, die Pipeline-Variante von $lookup unterstützt komplexe bedingte Joins mit $$let-Variablen, und ein Index für das Fremdfeld verbessert die Join-Performance deutlich. Als Nächstes sehen wir uns $unwind zum Auflösen von Array-Feldern an.

Kostenlos starten

Lerne JavaScript mit einem KI-Tutor — kostenlos

Schreibe und führe echten Code in deinem Browser aus, bekomme sofortige Hilfe von einem 24/7 KI-Tutor und setze dein Lernen im Web oder in der App fort.

Kurse
30
Lektionen
120

Häufig gestellte Fragen

Ist die Lektion „$lookup: Collections in der Pipeline verknüpfen“ kostenlos?

Ja — der vollständige Text von „$lookup: Collections in der Pipeline verknüpfen“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des MongoDB Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der MongoDB Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „$lookup: Collections in der Pipeline verknüpfen“?

Sie führen mit $lookup Left-Outer-Joins zwischen Collections aus und verstehen die Performance-Auswirkungen von Joins über mehrere Collections hinweg. Du übst MongoDB Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um MongoDB Academy zu starten?

Keine Vorkenntnisse erforderlich. MongoDB Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „$lookup: Collections in der Pipeline verknüpfen“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser MongoDB Academy-Lektion Code schreiben und ausführen?

Ja. Jede MongoDB Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. $lookup: Collections in der Pipeline verknüpfen
  2. $unwind: Array-Felder auflösen
  3. $addFields, $replaceRoot und $mergeObjects
  4. $out und $merge: Pipeline-Ergebnisse schreiben
← Zurück zu MongoDB Academy