Title: How to use mongoose to save multiple documents?
Tags: node.js;mongodb;mongoose
Question: I have 2 models here user and blog. So when an user write a blog, my router invoke them like this.
Promise.all([
node.save(),
user.save()
]).then(function (values) {
//do something
}).catch(function (err) {
//print error
})
As you may notice immediately, there's no guarantee for save(). Either of them could fails and no rollback for the rest. How can I make sure both of them are saved or rollbacked? Some people suggest to put blogs collection inside users so everything is in a single document, but that's hard to do blog ranking, isn't it? I'm also not sure if it's really a good practice that putting all things together in MongoDB. if documents are large, will it cause performance issues(say requests/second)?
Thanks.
Comment: Question is *"Why are you using `.save()`?"*. It "kind of" returns a promise, but it will actually fire beforehand. So the ouput would join in `Promise.all()`, but the actual sequence would occur on the `.save()`. If these are "new" then you could use `.create()` instead, which respects the promise just fine. If they are "updates" then you probably should be using `.findOneAndUpdate()` instead anyway.

Comment: Hi, I want both `node` and `user` to be saved correctly. Promise can tell me if there's any error so I can return appropriate http code to clients. Then I find even if I know there's an error, I can't rollback those saved data. I'm new to MongoDB and have no idea why it has been designed in this way :o

Here is the accepted answer: You can't use Promise.all, you'll have to chain your promises individually.
node.save().then(user.save).then(function(){//do something else});
You'll also have to work a little harder to get all the entities in an array like you get with Promise.all.  But do you really need that?  You have access to the user and the node entities already.
The classic way to do this would be using async and series:
async.series({
node: node.save,
user:user.save
}, function(err, res){
// res is now equal to: {node:node, user:user}
});
Most people simply don't bother with two phase commits using Mongo. If you really need this, perhaps you are using the wrong tool.
If the node save fails, the user won't be saved.  If you can't save the node without the user being saved, reverse the order order of operations.  If both MUST be updated for either to be, I'd probably rethink my data model.
If you really need a two phase commit, you need to reinvent that particular wheel. There's a recipe for doing it in the documentation. Or you can try one of the mongoose plugins that purport to do it.
Comment for this answer: Appreciate! Now I know what‘s exactly going one here :D


{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 1, 'CommentCount': 2, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2016:00:04/19/16', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<node.js><mongodb><mongoose>', 'Title': 'How to use mongoose to save multiple documents?', 'ViewCount': 3768, 'id': 36708109, 'user_AboutMe': '', 'user_AccountId': 2360184.0, 'user_DisplayName': 'zhuchun', 'user_Reputation': 193.0, 'user_Views': 33.0, 'user_id': 2067019.0}}