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.
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.
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 userskoleksi dan commentskoleksi dan Anda ingin memiliki koleksi baru yang memiliki beberapa info demografis pengguna untuk setiap komentar.
Katakanlah userskoleksi memiliki bidang-bidang berikut:
Dan kemudian commentskoleksi memiliki bidang-bidang berikut:
Anda akan melakukan peta ini / mengurangi:
var mapUsers, mapComments, reduce;
db.users_comments.remove();
// setup sample data - wouldn't actually use this in production
db.users.remove();
db.comments.remove();
db.users.save({firstName:"Rich",lastName:"S",gender:"M",country:"CA",age:"18"});
db.users.save({firstName:"Rob",lastName:"M",gender:"M",country:"US",age:"25"});
db.users.save({firstName:"Sarah",lastName:"T",gender:"F",country:"US",age:"13"});
var users = db.users.find();
db.comments.save({userId: users[0]._id, "comment": "Hey, what's up?", created: new ISODate()});
db.comments.save({userId: users[1]._id, "comment": "Not much", created: new ISODate()});
db.comments.save({userId: users[0]._id, "comment": "Cool", created: new ISODate()});
// end sample data setup
mapUsers = function() {
var values = {
country: this.country,
gender: this.gender,
age: this.age
};
emit(this._id, values);
};
mapComments = function() {
var values = {
commentId: this._id,
comment: this.comment,
created: this.created
};
emit(this.userId, values);
};
reduce = function(k, values) {
var result = {}, commentFields = {
"commentId": '',
"comment": '',
"created": ''
};
values.forEach(function(value) {
var field;
if ("comment" in value) {
if (!("comments" in result)) {
result.comments = [];
}
result.comments.push(value);
} else if ("comments" in value) {
if (!("comments" in result)) {
result.comments = [];
}
result.comments.push.apply(result.comments, value.comments);
}
for (field in value) {
if (value.hasOwnProperty(field) && !(field in commentFields)) {
result[field] = value[field];
}
}
});
return result;
};
db.users.mapReduce(mapUsers, reduce, {"out": {"reduce": "users_comments"}});
db.comments.mapReduce(mapComments, reduce, {"out": {"reduce": "users_comments"}});
db.users_comments.find().pretty(); // see the resulting collection
Pada titik ini, Anda akan memiliki koleksi baru yang disebut users_commentsyang berisi data yang digabungkan dan sekarang Anda dapat menggunakannya. Semua koleksi yang diperkecil ini memiliki _idkunci yang Anda keluarkan dalam fungsi peta Anda dan kemudian semua nilainya adalah sub-objek di dalam valuekunci - 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:
reduce = function(k, values) {
var result = {};
values.forEach(function(value) {
var field;
for (field in value) {
if (value.hasOwnProperty(field)) {
result[field] = value[field];
}
}
});
return result;
};
Jika Anda ingin meratakan users_commentskoleksi jadi satu dokumen per komentar, jalankan ini juga:
var map, reduce;
map = function() {
var debug = function(value) {
var field;
for (field in value) {
print(field + ": " + value[field]);
}
};
debug(this);
var that = this;
if ("comments" in this.value) {
this.value.comments.forEach(function(value) {
emit(value.commentId, {
userId: that._id,
country: that.value.country,
age: that.value.age,
comment: value.comment,
created: value.created,
});
});
}
};
reduce = function(k, values) {
var result = {};
values.forEach(function(value) {
var field;
for (field in value) {
if (value.hasOwnProperty(field)) {
result[field] = value[field];
}
}
});
return result;
};
db.users_comments.mapReduce(map, reduce, {"out": "comments_with_demographics"});
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 ensureIndexkoleksi baru untuk memastikan bahwa kueri yang Anda lakukan terhadapnya berjalan dengan cepat (perlu diingat bahwa data Anda masih di dalam valuekunci, jadi jika Anda mengindeks comments_with_demographicspada createdwaktu komentar , itu akan menjadidb.comments_with_demographics.ensureIndex({"value.created": 1});
users_commentskoleksi setelah blok pertama kode gist.github.com/nolanamy/83d7fb6a9bf92482a1c4311ad9c78835
MongoDB 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:
{
"isbn": "978-3-16-148410-0",
"title": "Some cool book",
"author": "John Doe"
}
{
"isbn": "978-3-16-148999-9",
"title": "Another awesome book",
"author": "Jane Roe"
}
Dan koleksi kedua, disebut books_selling_data, memiliki data berikut:
{
"_id": ObjectId("56e31bcf76cdf52e541d9d26"),
"isbn": "978-3-16-148410-0",
"copies_sold": 12500
}
{
"_id": ObjectId("56e31ce076cdf52e541d9d28"),
"isbn": "978-3-16-148999-9",
"copies_sold": 720050
}
{
"_id": ObjectId("56e31ce076cdf52e541d9d29"),
"isbn": "978-3-16-148999-9",
"copies_sold": 1000
}
Untuk menggabungkan kedua koleksi hanyalah masalah menggunakan $ lookup dengan cara berikut:
db.books.aggregate([{
$lookup: {
from: "books_selling_data",
localField: "isbn",
foreignField: "isbn",
as: "copies_sold"
}
}])
Setelah agregasi ini, bookskoleksi akan terlihat seperti berikut:
{
"isbn": "978-3-16-148410-0",
"title": "Some cool book",
"author": "John Doe",
"copies_sold": [
{
"_id": ObjectId("56e31bcf76cdf52e541d9d26"),
"isbn": "978-3-16-148410-0",
"copies_sold": 12500
}
]
}
{
"isbn": "978-3-16-148999-9",
"title": "Another awesome book",
"author": "Jane Roe",
"copies_sold": [
{
"_id": ObjectId("56e31ce076cdf52e541d9d28"),
"isbn": "978-3-16-148999-9",
"copies_sold": 720050
},
{
"_id": ObjectId("56e31ce076cdf52e541d9d28"),
"isbn": "978-3-16-148999-9",
"copies_sold": 1000
}
]
}
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.
$lookupseharusnya 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_collectiondan masukkan satu per satu ke big_collection:
db.small_collection.find().forEach(function(obj){
db.big_collection.insert(obj)
});
Contoh sangat mendasar dengan $ lookup.
db.getCollection('users').aggregate([
{
$lookup: {
from: "userinfo",
localField: "userId",
foreignField: "userId",
as: "userInfoData"
}
},
{
$lookup: {
from: "userrole",
localField: "userId",
foreignField: "userId",
as: "userRoleData"
}
},
{ $unwind: { path: "$userInfoData", preserveNullAndEmptyArrays: true }},
{ $unwind: { path: "$userRoleData", preserveNullAndEmptyArrays: true }}
])
Di sini digunakan
{ $unwind: { path: "$userInfoData", preserveNullAndEmptyArrays: true }},
{ $unwind: { path: "$userRoleData", preserveNullAndEmptyArrays: true }}
Dari pada
{ $unwind:"$userRoleData"}
{ $unwind:"$userRoleData"}
Karena {$ melepas: "$ userRoleData"} ini akan kembali kosong atau hasil 0 jika tidak ada catatan yang cocok dengan $ lookup.
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:
// Create employees data for testing the union.
db.getCollection('employees').insert({ name: "John", type: "employee", department: "sales" });
db.getCollection('employees').insert({ name: "Martha", type: "employee", department: "accounting" });
db.getCollection('employees').insert({ name: "Amy", type: "employee", department: "warehouse" });
db.getCollection('employees').insert({ name: "Mike", type: "employee", department: "warehouse" });
// Create freelancers data for testing the union.
db.getCollection('freelancers').insert({ name: "Stephany", type: "freelancer", department: "accounting" });
db.getCollection('freelancers').insert({ name: "Martin", type: "freelancer", department: "sales" });
db.getCollection('freelancers').insert({ name: "Doug", type: "freelancer", department: "warehouse" });
db.getCollection('freelancers').insert({ name: "Brenda", type: "freelancer", department: "sales" });
// Here we do a union of the employees and freelancers using a single aggregation query.
db.getCollection('freelancers').aggregate( // 1. Use any collection containing at least one document.
[
{ $limit: 1 }, // 2. Keep only one document of the collection.
{ $project: { _id: '$$REMOVE' } }, // 3. Remove everything from the document.
// 4. Lookup collections to union together.
{ $lookup: { from: 'employees', pipeline: [{ $match: { department: 'sales' } }], as: 'employees' } },
{ $lookup: { from: 'freelancers', pipeline: [{ $match: { department: 'sales' } }], as: 'freelancers' } },
// 5. Union the collections together with a projection.
{ $project: { union: { $concatArrays: ["$employees", "$freelancers"] } } },
// 6. Unwind and replace root so you end up with a result set.
{ $unwind: '$union' },
{ $replaceRoot: { newRoot: '$union' } }
]);
Berikut ini penjelasan cara kerjanya:
Instantiate aggregatedari 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 $projectpanggung:
{ $project: { _id: '$$REMOVE' } }Agregat Anda sekarang berisi satu dokumen kosong. Saatnya menambahkan pencarian untuk setiap koleksi yang ingin Anda satukan bersama. Anda dapat menggunakan pipelinebidang ini untuk melakukan pemfilteran tertentu, atau meninggalkan localFielddan foreignFieldsebagai nol 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 menggabungkan mereka menjadi satu array menggunakan $project panggung bersama dengan $concatArraysoperator agregasi:
{
"$project" :
{
"Union" : { $concatArrays: ["$Collection1", "$Collection2", "$Collection3"] }
}
}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 $replaceRoottahap untuk membagi array Anda menjadi dokumen terpisah:
{ $unwind: "$Union" },
{ $replaceRoot: { newRoot: "$Union" } }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.
gunakan beberapa $ lookup untuk beberapa koleksi secara agregasi
pertanyaan:
db.getCollection('servicelocations').aggregate([
{
$match: {
serviceLocationId: {
$in: ["36728"]
}
}
},
{
$lookup: {
from: "orders",
localField: "serviceLocationId",
foreignField: "serviceLocationId",
as: "orders"
}
},
{
$lookup: {
from: "timewindowtypes",
localField: "timeWindow.timeWindowTypeId",
foreignField: "timeWindowTypeId",
as: "timeWindow"
}
},
{
$lookup: {
from: "servicetimetypes",
localField: "serviceTimeTypeId",
foreignField: "serviceTimeTypeId",
as: "serviceTime"
}
},
{
$unwind: "$orders"
},
{
$unwind: "$serviceTime"
},
{
$limit: 14
}
])
hasil:
{
"_id" : ObjectId("59c3ac4bb7799c90ebb3279b"),
"serviceLocationId" : "36728",
"regionId" : 1.0,
"zoneId" : "DXBZONE1",
"description" : "AL HALLAB REST EMIRATES MALL",
"locationPriority" : 1.0,
"accountTypeId" : 1.0,
"locationType" : "SERVICELOCATION",
"location" : {
"makani" : "",
"lat" : 25.119035,
"lng" : 55.198694
},
"deliveryDays" : "MTWRFSU",
"timeWindow" : [
{
"_id" : ObjectId("59c3b0a3b7799c90ebb32cde"),
"timeWindowTypeId" : "1",
"Description" : "MORNING",
"timeWindow" : {
"openTime" : "06:00",
"closeTime" : "08:00"
},
"accountId" : 1.0
},
{
"_id" : ObjectId("59c3b0a3b7799c90ebb32cdf"),
"timeWindowTypeId" : "1",
"Description" : "MORNING",
"timeWindow" : {
"openTime" : "09:00",
"closeTime" : "10:00"
},
"accountId" : 1.0
},
{
"_id" : ObjectId("59c3b0a3b7799c90ebb32ce0"),
"timeWindowTypeId" : "1",
"Description" : "MORNING",
"timeWindow" : {
"openTime" : "10:30",
"closeTime" : "11:30"
},
"accountId" : 1.0
}
],
"address1" : "",
"address2" : "",
"phone" : "",
"city" : "",
"county" : "",
"state" : "",
"country" : "",
"zipcode" : "",
"imageUrl" : "",
"contact" : {
"name" : "",
"email" : ""
},
"status" : "ACTIVE",
"createdBy" : "",
"updatedBy" : "",
"updateDate" : "",
"accountId" : 1.0,
"serviceTimeTypeId" : "1",
"orders" : [
{
"_id" : ObjectId("59c3b291f251c77f15790f92"),
"orderId" : "AQ18O1704264",
"serviceLocationId" : "36728",
"orderNo" : "AQ18O1704264",
"orderDate" : "18-Sep-17",
"description" : "AQ18O1704264",
"serviceType" : "Delivery",
"orderSource" : "Import",
"takenBy" : "KARIM",
"plannedDeliveryDate" : ISODate("2017-08-26T00:00:00.000Z"),
"plannedDeliveryTime" : "",
"actualDeliveryDate" : "",
"actualDeliveryTime" : "",
"deliveredBy" : "",
"size1" : 296.0,
"size2" : 3573.355,
"size3" : 240.811,
"jobPriority" : 1.0,
"cancelReason" : "",
"cancelDate" : "",
"cancelBy" : "",
"reasonCode" : "",
"reasonText" : "",
"status" : "",
"lineItems" : [
{
"ItemId" : "BNWB020",
"size1" : 15.0,
"size2" : 78.6,
"size3" : 6.0
},
{
"ItemId" : "BNWB021",
"size1" : 20.0,
"size2" : 252.0,
"size3" : 11.538
},
{
"ItemId" : "BNWB023",
"size1" : 15.0,
"size2" : 285.0,
"size3" : 16.071
},
{
"ItemId" : "CPMW112",
"size1" : 3.0,
"size2" : 25.38,
"size3" : 1.731
},
{
"ItemId" : "MMGW001",
"size1" : 25.0,
"size2" : 464.375,
"size3" : 46.875
},
{
"ItemId" : "MMNB218",
"size1" : 50.0,
"size2" : 920.0,
"size3" : 60.0
},
{
"ItemId" : "MMNB219",
"size1" : 50.0,
"size2" : 630.0,
"size3" : 40.0
},
{
"ItemId" : "MMNB220",
"size1" : 50.0,
"size2" : 416.0,
"size3" : 28.846
},
{
"ItemId" : "MMNB270",
"size1" : 50.0,
"size2" : 262.0,
"size3" : 20.0
},
{
"ItemId" : "MMNB302",
"size1" : 15.0,
"size2" : 195.0,
"size3" : 6.0
},
{
"ItemId" : "MMNB373",
"size1" : 3.0,
"size2" : 45.0,
"size3" : 3.75
}
],
"accountId" : 1.0
},
{
"_id" : ObjectId("59c3b291f251c77f15790f9d"),
"orderId" : "AQ137O1701240",
"serviceLocationId" : "36728",
"orderNo" : "AQ137O1701240",
"orderDate" : "18-Sep-17",
"description" : "AQ137O1701240",
"serviceType" : "Delivery",
"orderSource" : "Import",
"takenBy" : "KARIM",
"plannedDeliveryDate" : ISODate("2017-08-26T00:00:00.000Z"),
"plannedDeliveryTime" : "",
"actualDeliveryDate" : "",
"actualDeliveryTime" : "",
"deliveredBy" : "",
"size1" : 28.0,
"size2" : 520.11,
"size3" : 52.5,
"jobPriority" : 1.0,
"cancelReason" : "",
"cancelDate" : "",
"cancelBy" : "",
"reasonCode" : "",
"reasonText" : "",
"status" : "",
"lineItems" : [
{
"ItemId" : "MMGW001",
"size1" : 25.0,
"size2" : 464.38,
"size3" : 46.875
},
{
"ItemId" : "MMGW001-F1",
"size1" : 3.0,
"size2" : 55.73,
"size3" : 5.625
}
],
"accountId" : 1.0
},
{
"_id" : ObjectId("59c3b291f251c77f15790fd8"),
"orderId" : "AQ110O1705036",
"serviceLocationId" : "36728",
"orderNo" : "AQ110O1705036",
"orderDate" : "18-Sep-17",
"description" : "AQ110O1705036",
"serviceType" : "Delivery",
"orderSource" : "Import",
"takenBy" : "KARIM",
"plannedDeliveryDate" : ISODate("2017-08-26T00:00:00.000Z"),
"plannedDeliveryTime" : "",
"actualDeliveryDate" : "",
"actualDeliveryTime" : "",
"deliveredBy" : "",
"size1" : 60.0,
"size2" : 1046.0,
"size3" : 68.0,
"jobPriority" : 1.0,
"cancelReason" : "",
"cancelDate" : "",
"cancelBy" : "",
"reasonCode" : "",
"reasonText" : "",
"status" : "",
"lineItems" : [
{
"ItemId" : "MMNB218",
"size1" : 50.0,
"size2" : 920.0,
"size3" : 60.0
},
{
"ItemId" : "MMNB219",
"size1" : 10.0,
"size2" : 126.0,
"size3" : 8.0
}
],
"accountId" : 1.0
}
],
"serviceTime" : {
"_id" : ObjectId("59c3b07cb7799c90ebb32cdc"),
"serviceTimeTypeId" : "1",
"serviceTimeType" : "nohelper",
"description" : "",
"fixedTime" : 30.0,
"variableTime" : 0.0,
"accountId" : 1.0
}
}
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.
Mulai Mongo 4.4, kami dapat mencapai gabungan ini dalam pipa agregasi dengan $unionWithmenggabungkan tahap agregasi baru dengan operator $groupbaru $accumulator:
// > db.users.find()
// [{ user: 1, name: "x" }, { user: 2, name: "y" }]
// > db.books.find()
// [{ user: 1, book: "a" }, { user: 1, book: "b" }, { user: 2, book: "c" }]
// > db.movies.find()
// [{ user: 1, movie: "g" }, { user: 2, movie: "h" }, { user: 2, movie: "i" }]
db.users.aggregate([
{ $unionWith: "books" },
{ $unionWith: "movies" },
{ $group: {
_id: "$user",
user: {
$accumulator: {
accumulateArgs: ["$name", "$book", "$movie"],
init: function() { return { books: [], movies: [] } },
accumulate: function(user, name, book, movie) {
if (name) user.name = name;
if (book) user.books.push(book);
if (movie) user.movies.push(movie);
return user;
},
merge: function(userV1, userV2) {
if (userV2.name) userV1.name = userV2.name;
userV1.books.concat(userV2.books);
userV1.movies.concat(userV2.movies);
return userV1;
},
lang: "js"
}
}
}}
])
// { _id: 1, user: { books: ["a", "b"], movies: ["g"], name: "x" } }
// { _id: 2, user: { books: ["c"], movies: ["h", "i"], name: "y" } }
$unionWithmenggabungkan 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 $groupmerekam $userdan mengakumulasikan item menggunakan $accumulatoroperator yang memungkinkan akumulasi dokumen kustom ketika dikelompokkan:
accumulateArgs.init mendefinisikan negara yang akan diakumulasikan saat kita mengelompokkan elemen.accumulatefungsi memungkinkan melakukan tindakan kustom dengan catatan yang dikelompokkan dalam rangka membangun akumulasi negara. Misalnya, jika item yang dikelompokkan memiliki bookbidang yang ditentukan, maka kami memperbaruibooks bagian negara.mergedigunakan untuk menggabungkan dua kondisi internal. Ini hanya digunakan untuk agregasi yang berjalan pada kelompok yang terbengkalai atau ketika operasi melebihi batas memori.Ya, Anda dapat: Ambil fungsi utilitas yang saya tulis hari ini:
function shangMergeCol() {
tcol= db.getCollection(arguments[0]);
for (var i=1; i<arguments.length; i++){
scol= db.getCollection(arguments[i]);
scol.find().forEach(
function (d) {
tcol.insert(d);
}
)
}
}
Anda dapat melewati ke fungsi ini sejumlah koleksi, yang pertama akan menjadi target. Semua koleksi sisanya adalah sumber yang akan ditransfer ke target.
Cuplikan kode. Courtesy-Banyak posting di stack overflow termasuk yang ini.
db.cust.drop();
db.zip.drop();
db.cust.insert({cust_id:1, zip_id: 101});
db.cust.insert({cust_id:2, zip_id: 101});
db.cust.insert({cust_id:3, zip_id: 101});
db.cust.insert({cust_id:4, zip_id: 102});
db.cust.insert({cust_id:5, zip_id: 102});
db.zip.insert({zip_id:101, zip_cd:'AAA'});
db.zip.insert({zip_id:102, zip_cd:'BBB'});
db.zip.insert({zip_id:103, zip_cd:'CCC'});
mapCust = function() {
var values = {
cust_id: this.cust_id
};
emit(this.zip_id, values);
};
mapZip = function() {
var values = {
zip_cd: this.zip_cd
};
emit(this.zip_id, values);
};
reduceCustZip = function(k, values) {
var result = {};
values.forEach(function(value) {
var field;
if ("cust_id" in value) {
if (!("cust_ids" in result)) {
result.cust_ids = [];
}
result.cust_ids.push(value);
} else {
for (field in value) {
if (value.hasOwnProperty(field) ) {
result[field] = value[field];
}
};
}
});
return result;
};
db.cust_zip.drop();
db.cust.mapReduce(mapCust, reduceCustZip, {"out": {"reduce": "cust_zip"}});
db.zip.mapReduce(mapZip, reduceCustZip, {"out": {"reduce": "cust_zip"}});
db.cust_zip.find();
mapCZ = function() {
var that = this;
if ("cust_ids" in this.value) {
this.value.cust_ids.forEach(function(value) {
emit(value.cust_id, {
zip_id: that._id,
zip_cd: that.value.zip_cd
});
});
}
};
reduceCZ = function(k, values) {
var result = {};
values.forEach(function(value) {
var field;
for (field in value) {
if (value.hasOwnProperty(field)) {
result[field] = value[field];
}
}
});
return result;
};
db.cust_zip_joined.drop();
db.cust_zip.mapReduce(mapCZ, reduceCZ, {"out": "cust_zip_joined"});
db.cust_zip_joined.find().pretty();
var flattenMRCollection=function(dbName,collectionName) {
var collection=db.getSiblingDB(dbName)[collectionName];
var i=0;
var bulk=collection.initializeUnorderedBulkOp();
collection.find({ value: { $exists: true } }).addOption(16).forEach(function(result) {
print((++i));
//collection.update({_id: result._id},result.value);
bulk.find({_id: result._id}).replaceOne(result.value);
if(i%1000==0)
{
print("Executing bulk...");
bulk.execute();
bulk=collection.initializeUnorderedBulkOp();
}
});
bulk.execute();
};
flattenMRCollection("mydb","cust_zip_joined");
db.cust_zip_joined.find().pretty();
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 @Referencepenjelasannya mengambil entitas yang direferensikan ketika ditanya, jadi saya dapat menghindari melakukannya sendiri dalam kode.
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.