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