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

$unionWith – MongoDBs Äquivalent zu UNION ALL

Wenn Sie mit SQL vertraut sind, kennen Sie vielleicht die UNION -Klausel, die die Ergebnisse zweier Abfragen zu einer einzigen Ergebnismenge verkettet. Insbesondere UNION ALL enthält Duplikate.

In MongoDB können wir den $unionWith verwenden Aggregation-Pipeline-Stufe, um den gleichen Effekt zu erzielen wie UNION ALL produziert. Die $unionWith stage führt eine Vereinigung von zwei Sammlungen durch – es kombiniert Pipeline-Ergebnisse aus zwei Sammlungen in einer einzigen Ergebnismenge. Und es enthält Duplikate.

Beispiel

Angenommen, wir erstellen zwei Sammlungen; eine namens cats und eine andere namens dogs . Und wir fügen die folgenden Dokumente in sie ein:

db.cats.insertMany([
    { _id: 1, name: "Fluffy", type: "Cat", weight: 5 },
    { _id: 2, name: "Scratch", type: "Cat", weight: 3 },
    { _id: 3, name: "Meow", type: "Cat", weight: 7 }
    ])

db.dogs.insertMany([
    { _id: 1, name: "Wag", type: "Dog", weight: 20 },
    { _id: 2, name: "Bark", type: "Dog", weight: 10 },
    { _id: 3, name: "Fluffy", type: "Dog", weight: 40 }
    ]) 

Wir können jetzt Abfragen für diese Sammlungen ausführen und den $unionWith verwenden Stufe, um die Ergebnisse der einzelnen Abfragen zu kombinieren.

Beispiel:

db.cats.aggregate( [
   { $set: { _id: "$_id" } },
   { $unionWith: { coll: "dogs", pipeline: [ { $set: { _id: "$_id" } } ] } },
   { $sort: { type: 1, weight: -1, name: 1 } }
] ) 

Ergebnis:

{ "_id" :3, "name" :"Miau", "typ" :"Katze", "gewicht" :7 }{ "_id" :1, "name" :"Fluffy", "typ" :„Katze“, „Gewicht“ :5 }{ „_id“ :2, „Name“ :„Scratch“, „Typ“ :„Katze“, „Gewicht“ :3 }{ „_id“ :3, „Name“ :„Fluffy“, „Typ“ :„Hund“, „Gewicht“ :40 }{ „_id“ :1, „Name“ :„Wag“, „Typ“ :„Hund“, „Gewicht“ :20 }{ „ _id“ :2, „name“ :„Bark“, „type“ :„Hund“, „weight“ :10 }

In diesem Beispiel hat jedes Dokument ein Typfeld mit entweder cat oder dog und so ist ganz klar, welches Dokument aus welcher Sammlung stammt.

Wenn die Dokumente jedoch kein Typfeld hätten, wäre es schwieriger herauszufinden, wo eine Sammlung endet und eine andere beginnt. In diesem Fall können wir bei $set ein String-Literal verwenden Bühne, um den Sammlungsnamen darzustellen.

Beispiel:

db.cats.aggregate( [
   { $set: { _id: "cat" } },
   { $unionWith: { coll: "dogs", pipeline: [ { $set: { _id: "dog" } } ] } },
   { $sort: { type: 1, weight: -1, name: 1 } }
] ) 

Ergebnis:

{ „_id“ :„cat“, „name“ :„Miau“, „type“ :„Cat“, „weight“ :7 }{ „_id“ :„cat“, „name“ :„Fluffy“ , „Typ“ :„Katze“, „Gewicht“ :5 }{ „_id“ :„Katze“, „Name“ :„Scratch“, „Typ“ :„Katze“, „Gewicht“ :3 }{ „_id“ :„Hund“, „Name“ :„Fluffy“, „Typ“ :„Hund“, „Gewicht“ :40 }{ „_id“ :„Hund“, „Name“ :„Wag“, „Typ“ :„Hund ", "Gewicht" :20 }{ "_id" :"Hund", "Name" :"Bell", "Typ" :"Hund", "Gewicht" :10 }

Sammlungsübergreifend sortieren

In den vorherigen Beispielen wurden die Katzen und die Hunde so sortiert, dass sie in zwei unterschiedliche Gruppen getrennt wurden; Erst Katzen, dann Hunde. Dies geschah hauptsächlich, weil wir nach type sortiert haben Feld zuerst.

Aber wir können es nach jedem anderen Feld sortieren, was dazu führen könnte, dass Katzen und Hunde kombiniert werden.

Beispiel:

db.cats.aggregate( [
   { $set: { _id: "cat" } },
   { $unionWith: { coll: "dogs", pipeline: [ { $set: { _id: "dog" } } ] } },
   { $sort: { name: 1 } }
] ) 

Ergebnis:

{ "_id" :"dog", "name" :"Bark", "type" :"Hund", "weight" :10 }{ "_id" :"cat", "name" :"Fluffy" , „Typ“ :„Katze“, „Gewicht“ :5 }{ „_id“ :„Hund“, „Name“ :„Fluffy“, „Typ“ :„Hund“, „Gewicht“ :40 }{ „_id“ :„cat“, „name“ :„Meow“, „type“ :„Cat“, „weight“ :7 }{ „_id“ :„cat“, „name“ :„Scratch“, „type“ :„Cat ", "Gewicht" :3 }{ "_id" :"Hund", "Name" :"Wag", "Typ" :"Hund", "Gewicht" :20 }

Projektionen

Sie können das $project verwenden stage, um anzugeben, welche Felder an die nächste Stufe in der Pipeline weitergegeben werden sollen. So können Sie beispielsweise die Anzahl der von der Abfrage zurückgegebenen Felder reduzieren.

Beispiel:

db.cats.aggregate( [
   { $project: { name: 1, _id: 0 } },
   { $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} }
] ) 

Ergebnis:

{ "name" :"Fluffy" }{ "name" :"Scratch" }{ "name" :"Miau" }{ "name" :"Wag" }{ "name" :"Bark" }{ " name" :"Fluffy" }

Duplikate entfernen

Sie können die $group verwenden Stufe, um redundante Duplikate aus dem Ergebnis zu entfernen.

Die vorherige Abfrage hat beispielsweise zwei Haustiere namens Fluffy zurückgegeben. Wir können eine $group hinzufügen Schritt zu dieser Abfrage, um das redundante Duplikat zu eliminieren, sodass nur ein Fluffy zurückgegeben wird.

db.cats.aggregate( [
   { $project: { name: 1, _id: 0 } },
   { $unionWith: { coll: "dogs", pipeline: [ { $project: { name: 1, _id: 0 } } ]} },
   { $group: { _id: "$name" } }
] ) 

Ergebnis:

{ "_id" :"Miau" }{ "_id" :"Bark" }{ "_id" :"Scratch" }{ "_id" :"Wag" }{ "_id" :"Fluffy" } 

Diesmal wird nur ein Fluffy zurückgegeben.

Nicht übereinstimmende Spalten

Einer der Vorteile von MongoDBs $unionWith hat über UNION ALL von SQL ist, dass es mit nicht übereinstimmenden Spalten verwendet werden kann.

Die SQL UNION -Klausel erfordert Folgendes:

  • Beide Abfragen geben die gleiche Anzahl von Spalten zurück
  • Die Spalten in derselben Reihenfolge
  • Die übereinstimmenden Spalten müssen einen kompatiblen Datentyp haben

Die MongoDB $unionWith Stage erlegt diese Beschränkungen nicht auf.

Daher könnten wir $unionWith verwenden um so etwas zu tun:

db.cats.aggregate( [
   { $set: { _id: "$_id" } },
   { $unionWith: { coll: "employees", pipeline: [ { $set: { _id: "$_id" } } ] } },
   { $sort: { type: 1, salary: -1 } }
] ) 

Ergebnis:

{ "_id" :2, "name" :"Sarah", "salary" :128000 }{ "_id" :5, "name" :"Beck", "salary" :82000 }{ "_id" :4, „name“ :„Chris“, „salary“ :45000 }{ „_id“ :3, „name“ :„Fritz“, „salary“ :25000 }{ „_id“ :1, „name“ :„Fluffy ", "type" :"Cat", "weight" :5 }{ "_id" :2, "name" :"Scratch", "type" :"Cat", "weight" :3 }{ "_id" :3, „Name“ :„Miau“, „Typ“ :„Katze“, „Gewicht“ :7 }

In diesem Fall haben wir uns den cats angeschlossen Sammlung mit den employees Sammlung. Die employees Die Sammlung hatte nicht die gleichen Felder wie die cats Sammlung, aber das ist in Ordnung – es hat trotzdem funktioniert.