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
aggregate
dari 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
$project
tahapan:{ $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
pipeline
untuk melakukan pemfilteran tertentu, atau tinggalkanlocalField
danforeignField
sebagai 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
$project
stage bersama dengan$concatArrays
operator 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
$unwind
dan$replaceRoot
stage 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.