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
aggregatez 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ą
$projectetapy:{ $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ć
pipelinepole, aby wykonać określone filtrowanie, lub pozostawićlocalFieldiforeignFieldjako 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ą
$projectetap wraz z$concatArraysoperator 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ć
$unwindi$replaceRootetap, 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.