Bagaimana saya (dalam MongoDB) dapat menggabungkan data dari banyak koleksi menjadi satu koleksi?
Bisakah saya menggunakan pengurangan peta dan jika demikian, bagaimana caranya?
Saya akan sangat menghargai beberapa contoh karena saya seorang pemula.
mongodb
mongodb-query
aggregation-framework
pengguna697697
sumber
sumber
db.collection1.find().forEach(function(doc){db.collection2.save(doc)});
sudah cukup. Silakan tentukan driver bekas Anda (java, php, ...) jika Anda tidak menggunakan mongo shell.Jawaban:
Meskipun Anda tidak dapat melakukan ini secara real-time, Anda dapat menjalankan pengurangan peta beberapa kali untuk menggabungkan data bersama dengan menggunakan opsi "perkecil" di MongoDB 1.8+ map / kurangi (lihat http://www.mongodb.org/ display / DOCS / MapReduce # MapReduce-Outputoptions ). Anda perlu memiliki beberapa kunci di kedua koleksi yang dapat Anda gunakan sebagai _id.
Misalnya, katakanlah Anda memiliki
users
koleksi dancomments
koleksi dan Anda ingin memiliki koleksi baru yang memiliki beberapa info demografis pengguna untuk setiap komentar.Katakanlah
users
koleksi memiliki bidang-bidang berikut:Dan kemudian
comments
koleksi memiliki bidang-bidang berikut:Anda akan melakukan peta ini / mengurangi:
Pada titik ini, Anda akan memiliki koleksi baru yang disebut
users_comments
yang berisi data yang digabungkan dan sekarang Anda dapat menggunakannya. Semua koleksi yang diperkecil ini memiliki_id
kunci yang Anda keluarkan dalam fungsi peta Anda dan kemudian semua nilainya adalah sub-objek di dalamvalue
kunci - nilainya tidak berada di tingkat teratas dari dokumen yang diperkecil ini.Ini adalah contoh yang agak sederhana. Anda dapat mengulangi ini dengan lebih banyak koleksi sebanyak yang Anda ingin terus membangun koleksi berkurang. Anda juga bisa melakukan ringkasan dan agregasi data dalam proses tersebut. Kemungkinan Anda akan mendefinisikan lebih dari satu fungsi pengurangan karena logika untuk menggabungkan dan mempertahankan bidang yang ada menjadi lebih kompleks.
Anda juga akan mencatat bahwa sekarang ada satu dokumen untuk setiap pengguna dengan semua komentar pengguna itu dalam sebuah array. Jika kami menggabungkan data yang memiliki hubungan satu-ke-satu dan bukan satu-ke-banyak, itu akan datar dan Anda bisa menggunakan fungsi pengurangan seperti ini:
Jika Anda ingin meratakan
users_comments
koleksi jadi satu dokumen per komentar, jalankan ini juga:Teknik ini seharusnya tidak dilakukan dengan cepat. Ini cocok untuk pekerjaan cron atau sesuatu seperti itu yang memperbarui data yang digabungkan secara berkala. Anda mungkin ingin menjalankan
ensureIndex
koleksi baru untuk memastikan bahwa kueri yang Anda lakukan terhadapnya berjalan dengan cepat (perlu diingat bahwa data Anda masih di dalamvalue
kunci, jadi jika Anda mengindekscomments_with_demographics
padacreated
waktu komentar , itu akan menjadidb.comments_with_demographics.ensureIndex({"value.created": 1});
sumber
users_comments
koleksi setelah blok pertama kode gist.github.com/nolanamy/83d7fb6a9bf92482a1c4311ad9c78835MongoDB 3.2 sekarang memungkinkan seseorang untuk menggabungkan data dari banyak koleksi menjadi satu melalui tahap agregasi $ lookup . Sebagai contoh praktis, katakanlah Anda memiliki data tentang buku yang dipecah menjadi dua koleksi yang berbeda.
Pengumpulan pertama, disebut
books
, memiliki data berikut:Dan koleksi kedua, disebut
books_selling_data
, memiliki data berikut:Untuk menggabungkan kedua koleksi hanyalah masalah menggunakan $ lookup dengan cara berikut:
Setelah agregasi ini,
books
koleksi akan terlihat seperti berikut:Penting untuk mencatat beberapa hal:
books_selling_data
, tidak dapat dibelokkan.Jadi, sebagai kesimpulan, jika Anda ingin mengkonsolidasikan kedua koleksi, memiliki, dalam hal ini, bidang datar salinan_sold dengan total salinan terjual, Anda harus bekerja sedikit lebih, mungkin menggunakan koleksi perantara yang akan, kemudian, menjadi $ keluar ke koleksi akhir.
sumber
$lookup
seharusnya tidak semua "localField" dan "foreignField" sama dengan "isbn"? bukan "_id" dan "isbn"?Jika tidak ada sisipan massal ke mongodb, kami lilitkan semua objek di dalam
small_collection
dan masukkan satu per satu kebig_collection
:sumber
Contoh sangat mendasar dengan $ lookup.
Di sini digunakan
Dari pada
Karena {$ melepas: "$ userRoleData"} ini akan kembali kosong atau hasil 0 jika tidak ada catatan yang cocok dengan $ lookup.
sumber
Melakukan serikat di MongoDB dengan cara 'SQL UNION' dimungkinkan menggunakan agregasi bersama dengan pencarian, dalam satu permintaan. Berikut adalah contoh yang telah saya uji yang berfungsi dengan MongoDB 4.0:
Berikut ini penjelasan cara kerjanya:
Instantiate
aggregate
dari setiap koleksi database Anda yang memiliki setidaknya satu dokumen itu. Jika Anda tidak dapat menjamin koleksi apa pun dari basis data Anda tidak akan kosong, Anda dapat mengatasi masalah ini dengan membuat di basis data 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 pipa Anda menjadi
{ $limit: 1 }
. Ini akan menghapus semua dokumen koleksi kecuali yang pertama.Keluarkan semua bidang dokumen yang tersisa dengan menggunakan
$project
panggung:Agregat Anda sekarang berisi satu dokumen kosong. Saatnya menambahkan pencarian untuk setiap koleksi yang ingin Anda satukan bersama. Anda dapat menggunakan
pipeline
bidang ini untuk melakukan pemfilteran tertentu, atau meninggalkanlocalField
danforeignField
sebagai nol untuk mencocokkan seluruh koleksi.Anda sekarang memiliki agregat yang berisi satu dokumen yang berisi 3 array seperti ini:
Anda kemudian dapat menggabungkan mereka menjadi satu array menggunakan
$project
panggung bersama dengan$concatArrays
operator agregasi:Anda sekarang memiliki agregat yang berisi satu dokumen, yang di dalamnya terdapat array yang berisi gabungan koleksi Anda. Yang masih harus dilakukan adalah menambahkan
$unwind
dan$replaceRoot
tahap untuk membagi array Anda menjadi dokumen terpisah:Voa. Anda sekarang memiliki kumpulan hasil yang berisi koleksi yang ingin Anda satukan bersama. Anda kemudian dapat menambahkan lebih banyak tahapan untuk memfilternya lebih lanjut, mengurutkannya, menerapkan lewati () dan batas (). Apa pun yang Anda inginkan.
sumber
gunakan beberapa $ lookup untuk beberapa koleksi secara agregasi
pertanyaan:
hasil:
sumber
Mongorestore memiliki fitur penambahan ini di atas apa pun yang sudah ada dalam database, sehingga perilaku ini dapat digunakan untuk menggabungkan dua koleksi:
Belum mencobanya, tetapi mungkin kinerjanya lebih cepat daripada pendekatan peta / pengurangan.
sumber
Mulai
Mongo 4.4
, kami dapat mencapai gabungan ini dalam pipa agregasi dengan$unionWith
menggabungkan tahap agregasi baru dengan operator$group
baru$accumulator
:$unionWith
menggabungkan catatan dari koleksi yang diberikan dalam dokumen yang sudah ada dalam pipa agregasi. Setelah 2 tahap penyatuan, kami memiliki semua catatan pengguna, buku, dan film dalam pipa.Kami kemudian
$group
merekam$user
dan mengakumulasikan item menggunakan$accumulator
operator yang memungkinkan akumulasi dokumen kustom ketika dikelompokkan:accumulateArgs
.init
mendefinisikan negara yang akan diakumulasikan saat kita mengelompokkan elemen.accumulate
fungsi memungkinkan melakukan tindakan kustom dengan catatan yang dikelompokkan dalam rangka membangun akumulasi negara. Misalnya, jika item yang dikelompokkan memilikibook
bidang yang ditentukan, maka kami memperbaruibooks
bagian negara.merge
digunakan untuk menggabungkan dua kondisi internal. Ini hanya digunakan untuk agregasi yang berjalan pada kelompok yang terbengkalai atau ketika operasi melebihi batas memori.sumber
Ya, Anda dapat: Ambil fungsi utilitas yang saya tulis hari ini:
Anda dapat melewati ke fungsi ini sejumlah koleksi, yang pertama akan menjadi target. Semua koleksi sisanya adalah sumber yang akan ditransfer ke target.
sumber
Cuplikan kode. Courtesy-Banyak posting di stack overflow termasuk yang ini.
sumber
Anda harus melakukannya di lapisan aplikasi Anda. Jika Anda menggunakan ORM, itu bisa menggunakan anotasi (atau yang serupa) untuk menarik referensi yang ada di koleksi lain. Saya hanya pernah bekerja dengan Morfia , dan
@Reference
penjelasannya mengambil entitas yang direferensikan ketika ditanya, jadi saya dapat menghindari melakukannya sendiri dalam kode.sumber