Tworzenie unii w MongoDB w sposób „SQL UNION” jest możliwe przy użyciu agregacji wraz z wyszukiwaniami w jednym zapytaniu.
Coś takiego:
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.
]);
Oto wyjaśnienie, jak to działa:
-
Utwórz wystąpienie
aggregate
z dowolnych zbiór Twojej bazy danych, który zawiera co najmniej jeden dokument. Jeśli nie możesz zagwarantować, że jakakolwiek kolekcja w Twojej bazie danych nie będzie pusta, możesz obejść ten problem, tworząc w swojej bazie danych rodzaj „fikcyjnej” kolekcji zawierającej pojedynczy pusty dokument, który będzie tam przeznaczony specjalnie do wykonywania zapytań składających. -
Ustaw pierwszy etap potoku jako
{ $limit: 1 }
. Spowoduje to usunięcie wszystkich dokumentów kolekcji z wyjątkiem pierwszego. -
Usuń wszystkie pola z pozostałego dokumentu za pomocą
$project
etapy:{ $project: { _id: 1 } }, { $project: { _id: 0 } }
-
Twój agregat zawiera teraz pojedynczy, pusty dokument. Czas dodać odnośniki do każdej kolekcji, którą chcesz połączyć. Możesz użyć
pipeline
pole, aby wykonać określone filtrowanie, lub pozostawićlocalField
iforeignField
jako null, aby dopasować całą kolekcję.{ $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } }, { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } }, { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } }
-
Masz teraz agregat zawierający pojedynczy dokument, który zawiera 3 tablice, takie jak ta:
{ Collection1: [...], Collection2: [...], Collection3: [...] }
Następnie możesz połączyć je w jedną tablicę za pomocą
$project
etap wraz z$concatArrays
operator agregacji:{ "$project" : { "Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] } } }
-
Masz teraz agregat zawierający pojedynczy dokument, w którym znajduje się tablica zawierająca twoją unię kolekcji. Pozostaje tylko dodać
$unwind
i$replaceRoot
etap, aby podzielić tablicę na oddzielne dokumenty:{ $unwind: "$Union" }, { $replaceRoot: { newRoot: "$Union" } }
-
Voila. Wiesz, że masz zestaw wyników zawierający kolekcje, które chciałeś połączyć. Następnie możesz dodać więcej etapów, aby je dalej filtrować, posortować, zastosować skip() i limit(). Prawie wszystko, co chcesz.