MongoDB

MongoDB ist die führende Open-Source, Document Datenbank die für einfache Entwicklung und Skalierung aber auch für Big Data Szenarien entwickelt wurde.

MongoDB $lookup - JOIN´s auf Dokumente

Marc-David Militz
Expert
Wer mit dem Konzept von MongoDB Aggregation Stages noch nicht vertraut ist, sollte zuerst diesen Artikel lesen.
https://www.qualiero.com/community/mongodb/mongodb-theorie/mongodb-aggregation-pipeline-in-5-minuten.html

Mit der $lookup Stage ist es möglich, Collections in einer Datenbank zu joinen. $lookup gibt dabei die Dokumente einer gejointen Collection als Unter-Array der Original Collection zurück. Von $lookup werden dabei sowohl grundlegende Vergleiche auf Gleichheit wie auch unkorrelierte Unterabfragen unterstützt. Zu beiden Varianten hier nun ein paar erklärende Beispiele:

  • Beispieldaten

    • Wir haben zwei Collections. Die Collections "Posts" und "Kommentare", beide enthalten Dokumente mit übereinstimmenden Titeln. Beide Collections enthalten zudem "likes".
      Posts Collection

      {
      "title" : "my first post",
      "author" : "Jim",
      "likes" : 5
      },
      {
      "title" : "my second post",
      "author" : "Jim",
      "likes" : 2
      },
      {
      "title" : "hello world",
      "author" : "Joe",
      "likes" : 3
      }


      Kommentare Collection

      {
      "postTitle" : "my first post",
      "comment" : "great read",
      "likes" : 3
      },
      {
      "postTitle" : "my second post",
      "comment" : "good info",
      "likes" : 0
      },
      {
      "postTitle" : "my second post",
      "comment" : "i liked this post",
      "likes" : 12
      },
      {
      "postTitle" : "hello world",
      "comment" : "not my favorite",
      "likes" : 8
      },
      {
      "postTitle" : "my last post",
      "comment" : null,
      "likes" : 0
      }


      • $lookup Beispiel: einfacher Vergleich


        • db.posts.aggregate([
          { $lookup:
          {
          from: "comments",
          localField: "title",
          foreignField: "postTitle",
          as: "comments"
          }
          }
          ])

          Die $lookup Stage arbeitet nun folgendermaßen:
          "db.posts.aggregate": enthält die Collection, auf die die Aggregation angewendet wird.
          "from": benennt die Collection die wir joinen möchten
          "localField": bezeichnet das Feld aus "Posts" (local Collection) das für den join verwendet werden soll
          "foreignField": bezeichnet das Feld aus "Kommentare" (foreign Collection) das für den join verwendet werden soll
          "as": bestimmt den Namen des Ergebnis-Arrays

          Das Ergebnis der Abfrage sieht folgendermaßen aus ...
          {
          "title" : "my first post",
          "author" : "Jim",
          "likes" : 5,
          "comments" : [
          {
          "postTitle" : "my first post",
          "comment" : "great read",
          "likes" : 3
          }
          ]
          },
          {
          "title" : "my second post",
          "author" : "Jim",
          "likes" : 2,
          "comments" : [
          {
          "postTitle" : "my second post",
          "comment" : "good info",
          "likes" : 0
          },
          {
          "postTitle" : "my second post",
          "comment" : "i liked this post",
          "likes" : 12
          }
          ]
          },
          {
          "title" : "hello world",
          "author" : "Joe",
          "likes" : 3,
          "comments" : [
          {
          "postTitle" : "hello world",
          "comment" : "not my favorite",
          "likes" : 8
          }
          ]
          }


          Jedes Dokument aus der "Posts" Collection wird wird mit einem zusätzlichen Feld "comments" zurückgegeben. Jeder Post, der einen übereinstimmenden Titel mit einem (oder mehreren) Dokumenten in der Kommentare Collection hat, gibt diese als Array im Feld "comments" zurück.

          • $lookup example: Pipeline Beispiel mit Bedingungen


            • db.posts.aggregate([
              { $lookup:
              {
              from: "comments",
              let: { post_likes: "$likes", post_title: "$title"},
              pipeline: [
              { $match:
              { $expr:
              { $and:
              [
              { $gt: [ "$likes", "$$post_likes"] },
              { $eq: ["$$post_title", "$postTitle" ] }
              ]
              }
              }
              }
              ],
              as: "comments"
              }
              }
              ])

              Die "$lookup" Stage hat in diesem Beispiel etwas andere Felder. Die Parameter "localField" und "parentField" wurden nun ersetzt durch:
              "let" (optional): ein Ausdruck, der Variablen definiert die in der Pipeline Stage genutzt werden können. Damit ist es möglich Felder aus der Ursprünglichen Collection in die Pipeline zu bringen.
              "pipeline": eine Aggregation Pipeline, die auf die zu joinende Collection angewendet wird.

              Im "let" Ausdruck wurden zwei Variablen definiert. "post_likes" und "post_title" referenzieren auf die Eingabedokumente und können in der pipeline Stage verwendet werden. Nur auf diese Weise ist es möglich Collection übergreifende Vergleiche zu machen.

              { $gt: [ "$likes", "$$post_likes"] },
              { $eq: ["$$post_title", "$postTitle" ] }

              Die Syntax "$$" wird verwendet um um auf die in "let" definierten Variablen zu verweisen. Die Felder der gejointen Collection werden mit einem einfachen "$" referenziert.

              Das Ergebnis der Abfrage sieht wie folgt aus:

              {
              "title" : "my first post",
              "author" : "Jim",
              "likes" : 5,
              "comments" : []
              },
              {
              "title" : "my second post",
              "author" : "Jim",
              "likes" : 2,
              "comments" : [
              {
              "postTitle" : "my second post",
              "comment" : "i liked this post",
              "likes" : 12
              }
              ]
              },
              {
              "title" : "hello world",
              "author" : "Joe",
              "likes" : 3,
              "comments" : [
              {
              "postTitle" : "hello world",
              "comment" : "not my favorite",
              "likes" : 8
              }
              ]
              }

              Wie auch beim ersten Beispiel gibt diese Abfrage die Posts mit den Kommentaren zurück. In diesem Fall wird allerdings nach Kommentaren gesucht, die mehr likes erhalten haben als der eigentliche Post.

              • Zusammenfassung

                • Die beiden gezeigten Beispiele verdeutlichen die beiden Verwendungsformen von "$lookup". Je nach der verwendeten Variante gibt es leicht unterschiedliche Parameter. Man sollte allerdings bedenken, daß das Datenmodell von MongoDB auf einem Nicht-Relationalen Ansatz basiert.
                  Für schnelle Abfragen ist ein verschachteltes, traversierbares JSON Objekt immer schneller.

                  Wer mehr über die Möglichkeiten des Aggregation Frameworks erfahren möchte, dem sei der Qualiero Kurs für Datenbank Entwickler empfohlen
                  https://www.qualiero.com/lerninhalte/classroom-trainings/mongodb-datenbank-entwickler-kurs.html

Latest member activities

Recommend this community post