Melakukan penyatuan di MongoDB dengan cara 'SQL UNION' dimungkinkan menggunakan agregasi bersama dengan pencarian, dalam satu kueri.
Sesuatu seperti ini:
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.
]);
Berikut penjelasan cara kerjanya:
-
Buat instance
aggregatedari apa saja kumpulan database Anda yang memiliki setidaknya satu dokumen di dalamnya. Jika Anda tidak dapat menjamin koleksi database Anda tidak akan kosong, Anda dapat mengatasi masalah ini dengan membuat di database Anda semacam koleksi 'dummy' yang berisi satu dokumen kosong di dalamnya yang akan ada di sana khusus untuk melakukan kueri gabungan. -
Jadikan tahap pertama dari pipeline Anda menjadi
{ $limit: 1 }. Ini akan menghapus semua dokumen koleksi kecuali yang pertama. -
Hapus semua bidang dokumen yang tersisa dengan menggunakan
$projecttahapan:{ $project: { _id: 1 } }, { $project: { _id: 0 } } -
Agregat Anda sekarang berisi satu dokumen kosong. Saatnya menambahkan pencarian untuk setiap koleksi yang ingin Anda gabungkan bersama. Anda dapat menggunakan
pipelineuntuk melakukan pemfilteran tertentu, atau tinggalkanlocalFielddanforeignFieldsebagai null untuk mencocokkan seluruh koleksi.{ $lookup: { from: 'collectionToUnion1', pipeline: [...], as: 'Collection1' } }, { $lookup: { from: 'collectionToUnion2', pipeline: [...], as: 'Collection2' } }, { $lookup: { from: 'collectionToUnion3', pipeline: [...], as: 'Collection3' } } -
Anda sekarang memiliki agregat yang berisi satu dokumen yang berisi 3 array seperti ini:
{ Collection1: [...], Collection2: [...], Collection3: [...] }Anda kemudian dapat menggabungkannya menjadi satu larik menggunakan
$projectstage bersama dengan$concatArraysoperator agregasi:{ "$project" : { "Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] } } } -
Anda sekarang memiliki agregat yang berisi satu dokumen, di mana terletak array yang berisi gabungan koleksi Anda. Yang masih harus dilakukan adalah menambahkan
$unwinddan$replaceRootstage untuk membagi array Anda menjadi dokumen terpisah:{ $unwind: "$Union" }, { $replaceRoot: { newRoot: "$Union" } } -
Voila. Anda tahu memiliki kumpulan hasil yang berisi koleksi yang ingin Anda gabungkan bersama. Anda kemudian dapat menambahkan lebih banyak tahapan untuk memfilternya lebih lanjut, mengurutkannya, menerapkan skip() dan limit(). Hampir semua yang Anda inginkan.