Whether I'm creating or updating a record of type article, I have to use .save(). Before I hit save, I have the entire user in req.user
{ provider: 'local',
email: '[email protected]',
hashed_password: '49de749649b49c9bdf31073a8975bbc128b09d81',
salt: '298408390498',
username: 'test1',
name: 'test1',
_id: 540a2e06c09f8f4e922dd773,
__v: 0 }
Then I do:
var article = new Article(req.body.article);
article.user = req.user;
Mongoose only keeps the id part and when I try to get article.user out it just gives me the string 540a2e06c09f8f4e922dd773, the rest is scrapped. Using this id when I save, mongoose accurately saves the reference in mongo
article.save(function(err, article) {
res.jsonp({
article: article
});
});
But it returns the user as an id in the callback, not as an embedded record. Even if I try after the callback to attach the whole user object so I can return it to the client from the save callback, everything but id is scrapped.
If I want to make it embed, I normally call populate, but apparently I don't have that method after saving, only when I'm doing finds. Which means even though I already have the new record which I just saved or updated, I have to go _back_ to the database with a find so I can do a populate. (load is a convenience method I have for find then populate)
article.save(function(err) {
Article.load(article._id, function(err, result) {
if (err) {
return res.send('users/signup', {
errors: err.errors,
article: result
});
} else {
res.jsonp({
article: result
});
}
});
});
This is redundant and inefficient, it more than doubles the time needed to perform this operation and I was looking for a proper way to do this, but even the guides here for updating refs tell me to do a redundant find and populate...
Why not just set article.user
to the user id and then save article
and user
in parallel? Right now, since user is an ObjectId
, mongoose casts the user object to an ObjectId
new Trending({
location: req.body.location._id,
tag: req.body.tag._id,
addedBy: req.user._id,
addedOn: Date.now()
}).save(function(err, data) {
if(err) console.log('add trending err:', err);
else {
Trending.findById(data._id).populate('location tag').exec(function(err, data) {
if(err) console.log('add find trending err:', err);
else res.status(200).send(data);
});
}
});
Is there anyway to simplify this query? i mean save and then populate, instead of save(query) and then populate(query). @vkarpov15
@nasr18 not that I know of
its ok. why dont u make it??
Not really possible, closest thing is findOneAndUpdate but that has a few limitations. Plus I'm not sure a saveThenFind function would really provide much value
https://github.com/Automattic/mongoose/wiki/3.6-Release-Notes#syntax-support-for-population-of-multiple-fields
I guess you will find this interesting.
Model.populate(model ,opts,function(err,populdatedDoc){
})
@nasr18
ended up writing some curry-able Promise functions where you declare your schema, query_adapter, data_adapter functions and populate string in advance. For a shorter / simpler implementation easier on.
github file: curry_Promises.js
declartion
javascript
const update_or_insert_Item = mDB.update_or_insert({
schema : model.Item,
fn_query_adapter : ({ no })=>{return { no }},
fn_update_adapter : SQL_to_MDB.item,
populate : "headgroup"
// fn_err : (e)=>{return e},
// fn_res : (o)=>{return o}
})
execution
````javascript
Promise.all( items.map( update_or_insert_Item ) )
.catch( console.error )
.then( console.log )
`````
Most helpful comment
https://github.com/Automattic/mongoose/wiki/3.6-Release-Notes#syntax-support-for-population-of-multiple-fields
I guess you will find this interesting.
Model.populate(model ,opts,function(err,populdatedDoc){ })
@nasr18