Unions maken in MongoDB op een 'SQL UNION'-manier is mogelijk met behulp van aggregaties samen met lookups, in een enkele zoekopdracht.
Zoiets als dit:
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 is de uitleg van hoe het werkt:
-
Instantieer een
aggregate
uit elke verzameling van uw database die ten minste één document bevat. Als u niet kunt garanderen dat een verzameling van uw database niet leeg is, kunt u dit probleem omzeilen door in uw database een soort 'dummy'-verzameling te maken met daarin een enkel leeg document dat speciaal is bedoeld voor het uitvoeren van union-query's. -
Maak de eerste fase van uw pijplijn
{ $limit: 1 }
. Hiermee worden alle documenten van de collectie verwijderd, behalve de eerste. -
Verwijder alle velden van het resterende document met behulp van
$project
stadia:{ $project: { _id: 1 } }, { $project: { _id: 0 } }
-
Uw aggregaat bevat nu één leeg document. Het is tijd om zoekopdrachten toe te voegen voor elke verzameling die u wilt samenvoegen. U mag de
pipeline
. gebruiken veld om specifiek te filteren, of verlaatlocalField
enforeignField
als null om bij de hele collectie te passen.{ $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } }, { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } }, { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } }
-
U hebt nu een aggregaat dat een enkel document bevat dat 3 arrays bevat zoals deze:
{ Collection1: [...], Collection2: [...], Collection3: [...] }
Je kunt ze dan samenvoegen tot een enkele array met behulp van een
$project
stage samen met de$concatArrays
aggregatie-operator:{ "$project" : { "Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] } } }
-
U hebt nu een aggregaat dat één enkel document bevat, waarin zich een array bevindt die uw unie van verzamelingen bevat. Wat nog moet gebeuren, is het toevoegen van een
$unwind
en een$replaceRoot
stage om uw array op te splitsen in afzonderlijke documenten:{ $unwind: "$Union" }, { $replaceRoot: { newRoot: "$Union" } }
-
Voila. U weet dat u een resultatenset hebt met de collecties die u samen wilde voegen. U kunt dan meer fasen toevoegen om het verder te filteren, sorteren, skip() en limit() toepassen. Vrijwel alles wat je wilt.