MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

$unionWith — odpowiednik UNION ALL w MongoDB

Jeśli znasz SQL, możesz wiedzieć o UNION klauzula, która łączy wyniki dwóch zapytań w jeden zestaw wyników. W szczególności UNION ALL zawiera duplikaty.

W MongoDB możemy użyć $unionWith etap potoku agregacji, aby osiągnąć ten sam efekt, co UNION ALL produkuje. $unionWith stage wykonuje połączenie dwóch kolekcji — łączy wyniki potoku z dwóch kolekcji w jeden zestaw wyników. I zawiera duplikaty.

Przykład

Załóżmy, że tworzymy dwie kolekcje; jeden o nazwie cats i inny o nazwie dogs . Wstawiamy do nich następujące dokumenty:

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 }
    ])

Możemy teraz uruchamiać zapytania względem tych kolekcji i używać $unionWith etap łączenia wyników każdego zapytania.

Przykład:

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

Wynik:

{ "_id" : 3, "name" : "Meow", "type" : "Cat", "weight" : 7 }
{ "_id" : 1, "name" : "Fluffy", "type" : "Cat", "weight" : 5 }
{ "_id" : 2, "name" : "Scratch", "type" : "Cat", "weight" : 3 }
{ "_id" : 3, "name" : "Fluffy", "type" : "Dog", "weight" : 40 }
{ "_id" : 1, "name" : "Wag", "type" : "Dog", "weight" : 20 }
{ "_id" : 2, "name" : "Bark", "type" : "Dog", "weight" : 10 }

W tym przykładzie każdy dokument ma pole typu zawierające cat lub dog więc jest całkiem oczywiste, który dokument pochodzi z której kolekcji.

Ale gdyby dokumenty nie miały pola typu, to byłoby trudniej ustalić, gdzie kończy się jedna kolekcja, a zaczyna druga. W tym przypadku możemy użyć literału ciągu w $set etap reprezentujący nazwę kolekcji.

Przykład:

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

Wynik:

{ "_id" : "cat", "name" : "Meow", "type" : "Cat", "weight" : 7 }
{ "_id" : "cat", "name" : "Fluffy", "type" : "Cat", "weight" : 5 }
{ "_id" : "cat", "name" : "Scratch", "type" : "Cat", "weight" : 3 }
{ "_id" : "dog", "name" : "Fluffy", "type" : "Dog", "weight" : 40 }
{ "_id" : "dog", "name" : "Wag", "type" : "Dog", "weight" : 20 }
{ "_id" : "dog", "name" : "Bark", "type" : "Dog", "weight" : 10 }

Sortowanie w kolekcjach

W poprzednich przykładach koty i psy zostały posortowane w sposób, który podzielił je na dwie odrębne grupy; najpierw koty, potem psy. Stało się tak głównie dlatego, że sortowaliśmy według type najpierw pole.

Ale możemy to posortować na dowolnym innym polu, co może skutkować połączeniem kotów i psów.

Przykład:

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

Wynik:

{ "_id" : "dog", "name" : "Bark", "type" : "Dog", "weight" : 10 }
{ "_id" : "cat", "name" : "Fluffy", "type" : "Cat", "weight" : 5 }
{ "_id" : "dog", "name" : "Fluffy", "type" : "Dog", "weight" : 40 }
{ "_id" : "cat", "name" : "Meow", "type" : "Cat", "weight" : 7 }
{ "_id" : "cat", "name" : "Scratch", "type" : "Cat", "weight" : 3 }
{ "_id" : "dog", "name" : "Wag", "type" : "Dog", "weight" : 20 }

Projekcje

Możesz użyć $project etap, aby określić, które pola mają zostać przekazane do następnego etapu w potoku. Na przykład możesz zmniejszyć liczbę pól zwracanych przez zapytanie.

Przykład:

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

Wynik:

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

Usuń duplikaty

Możesz użyć $group etap, aby wyeliminować zbędne duplikaty z wyniku.

Na przykład poprzednie zapytanie zwróciło dwa zwierzaki o nazwie Fluffy. Możemy dodać $group etap do tego zapytania, aby wyeliminować zbędny duplikat, tak aby zwracany był tylko jeden Fluffy.

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

Wynik:

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

Tym razem zwracany jest tylko jeden Fluffy.

Niepasujące kolumny

Jedna z zalet $unionWith MongoDB ma ponad UNION ALL SQL jest to, że można go używać z niepasującymi kolumnami.

SQL UNION klauzula wymaga, aby:

  • Oba zapytania zwracają tę samą liczbę kolumn
  • Kolumny w tej samej kolejności
  • Dopasowane kolumny muszą mieć zgodny typ danych

MongoDB $unionWith scena nie nakłada tych ograniczeń.

Dlatego możemy użyć $unionWith zrobić coś takiego:

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

Wynik:

{ "_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" : "Meow", "type" : "Cat", "weight" : 7 }

W tym przypadku dołączyliśmy do cats zbiórka z employees kolekcja. employees kolekcja nie miała takich samych pól jak cats kolekcja, ale to w porządku – nadal działało.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Dlaczego mongoDB używa identyfikatora obiektu?

  2. Dlaczego MongoDB nie używa przecięcia indeksu?

  3. Jak mogę wyłączyć komunikaty dziennika MongoDB w konsoli?

  4. Nie można uruchomić obrazu docker mongo w systemie Windows

  5. Definiowanie schematu Mongoose na bieżąco z „opisu” w formacie JSON