MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

So schreiben Sie Union-Abfragen in MongoDB

Das Ausführen von Unions in MongoDB in einer 'SQL UNION'-Art ist möglich, indem Aggregationen zusammen mit Lookups in einer einzigen Abfrage verwendet werden.

Etwa so:

    db.getCollection("AnyCollectionThatContainsAtLeastOneDocument").aggregate(
    [
      { $limit: 1 }, // Reduce the result set to a single document.
      { $project: { _id: 1 } }, // Strip all fields except the Id.
      { $project: { _id: 0 } }, // Strip the id. The document is now empty.

      // Lookup all collections to union together.
      { $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } },
      { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } },
      { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } },

      // Merge the collections together.
      {
        $project:
        {
          Union: { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
        }
      },

      { $unwind: "$Union" }, // Unwind the union collection into a result set.
      { $replaceRoot: { newRoot: "$Union" } } // Replace the root to cleanup the resulting documents.
    ]);

Hier ist die Erklärung, wie es funktioniert:

  1. Instanziieren Sie ein aggregate aus irgendeinem Sammlung Ihrer Datenbank, die mindestens ein Dokument enthält. Wenn Sie nicht garantieren können, dass keine Sammlung Ihrer Datenbank leer ist, können Sie dieses Problem umgehen, indem Sie in Ihrer Datenbank eine Art „Dummy“-Sammlung erstellen, die ein einzelnes leeres Dokument enthält, das speziell für Union-Abfragen vorhanden ist.

  2. Machen Sie die erste Stufe Ihrer Pipeline zu { $limit: 1 } . Dadurch werden alle Dokumente der Sammlung außer dem ersten entfernt.

  3. Entfernen Sie alle Felder des verbleibenden Dokuments, indem Sie $project verwenden Stufen:

    { $project: { _id: 1 } },
    { $project: { _id: 0 } }
    
  4. Ihr Aggregat enthält jetzt ein einzelnes, leeres Dokument. Es ist an der Zeit, Lookups für jede Sammlung hinzuzufügen, die Sie zusammenführen möchten. Sie können die pipeline verwenden Feld, um eine bestimmte Filterung durchzuführen, oder lassen Sie localField und foreignField als null, um die gesamte Sammlung abzugleichen.

    { $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } },
    { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } },
    { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } }
    
  5. Sie haben jetzt ein Aggregat, das ein einzelnes Dokument enthält, das 3 Arrays wie dieses enthält:

    {
        Collection1: [...],
        Collection2: [...],
        Collection3: [...]
    }
    

    Sie können sie dann mit einem $project zu einem einzigen Array zusammenführen Bühne zusammen mit den $concatArrays Aggregationsoperator:

    {
      "$project" :
      {
        "Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
      }
    }
    
  6. Sie haben jetzt ein Aggregat, das ein einzelnes Dokument enthält, in dem sich ein Array befindet, das Ihre Vereinigung von Sammlungen enthält. Was noch zu tun bleibt, ist ein $unwind hinzuzufügen und ein $replaceRoot Stage, um Ihr Array in separate Dokumente aufzuteilen:

    { $unwind: "$Union" },
    { $replaceRoot: { newRoot: "$Union" } }
    
  7. Voilà. Sie wissen, dass Sie eine Ergebnismenge haben, die die Sammlungen enthält, die Sie zusammenführen möchten. Sie können dann weitere Stufen hinzufügen, um sie weiter zu filtern, zu sortieren, skip() und limit() anzuwenden. So ziemlich alles, was Sie wollen.