Reputation: 1133
I have the following simplified document from the collection "main":
{
_id: 120,
name: "Main1",
prop1: "val",
menuId: 5
}
Here is a simplified document from my "menu" collection:
{
_id: 5,
menuItems: [an array of elements here],
menuProperties: {an object here}
}
Is it possible to populate with mongoose.js the "menu" document into the "main" document in such way that will result the following model object:
{
_id: 120,
name: "Main1",
prop1: "val",
menuItems: [an array of elements here],
menuProperties: {an object here}
}
What i can achieve now is:
{
_id: 120,
name: "Main1",
prop1: "val",
menuId: {
menuItems: [an array of elements here],
menuProperties: {an object here}
}
}
I haven't added the schemes as they are very simple and will contain ref
for the menuId
.
Thanks!
Upvotes: 1
Views: 84
Reputation: 48376
One way is to remove the menuId
from population result, and add menuItem
and menuProperties
to the population result. Here are the sample codes,
Main.find()
.populate('menuId', 'menuItem menuProperties -_id', 'Menu')
.exec(function(err, docs){
if (err)
console.log(err);
else {
var rets = [];
docs.forEach(function(doc) {
// converts the mongoose document into a plain javascript object
doc = doc.toJSON();
// add menuItem key
if (doc.menuId && doc.menuId.menuItem) {
doc.menuItem = doc.menuId.menuItem;
}
// add menuProperties key
if (doc.menuId && doc.menuId.menuProperties) {
doc.menuProperties = doc.menuId.menuProperties;
// remove the menuId object
delete doc.menuId
}
rets.push(doc);
});
console.log(rets);
}
});
Test with schema
var MainSchema = new mongoose.Schema({
name: String,
prop1: String,
menuId: Number
});
var MenuSchema = new mongoose.Schema({
_id: Number,
menuItem: [String],
menuProperties: {k: String}
});
var Main = mongoose.model('Main', MainSchema);
var Menu = mongoose.model('Menu', MenuSchema);
And results are
[ { _id: 56fa39b4924d1254272ac3f1,
name: 'main1',
prop1: 'val',
__v: 0,
menuItem: [ 't1', 't2' ],
menuProperties: { k: 'p1' } } ]
Upvotes: 1
Reputation: 5606
There are many ways to do this. You could always do something like this (note, you didn't post your schemas so I made up the names):
//get every document in menu collection
Menu.find({}).exec(function(err,all_menuItems){
if (err) {throw err};
//for all documents in them meny collection
//find docuement in main collection and update
all_menuItems.forEach(function(item){
//wrapping in closure since doing forEach over async function
function(){
Main.findOne({_id:item._id}).exec(function(err,mainItem){
if (err) {throw err};
//set properties
mainItem.menuItems = item.menuItems;
menuItem.menuProperties = item.menuProperties;
//save document
Main.save(mainItem)
})
}(item)
})
})
Also, mongoose as a built in populate method which can be used to do this. You can find that documentation here. http://mongoosejs.com/docs/populate.html.
Using populate would probably be a much better option than looping over a bunch of async calls (or re-writing the above code to process the updates synchronously). But you can handle whatever way makes the most sense for your db.
Upvotes: 2