Search code examples
mongodbmongoosemongodb-querynosql

MongoDB - How to Ensure Multiple Updates were All Successfull?


Suppose you have an app where one single operation from the user involves updating multiple documents from different collections.

I actually have two questions ;-)

What is the best way to do it, and how to make sure that either everything is properly saved or the operation is canceled ?

Im using Mongoose

Solution A - Nested callbacks

Assuming both userId and eventId are provided by client side POST call or via socket

User.findById(userId,{},function(err,myUser){

if (err) { 
    console.log('Error updating user...');
    return;
} else {
    Event.findById(eventId,{},function(err,myEvent) {
     
    if (err) {
        console.log('Error updating user's Event...');
        return;
    } else {
        console.log('Both user and event were successfully updated');
        socket.emit('Update success!')  ||   res.send(...);
    });
});

Solution B - Parallel calls

User.findById(userId,{},function(err,myUser) {
    if (err){ 
        console.log('Error updating user...');
        return;
    } else {
        console.log('Success updating user');
        socket.emit('..')  ||  res.send('...');
    });

Event.findById(eventId,{},function(err,myEvent) {
    if (err){
        console.log('Error updating user's Event...');
        return;
    } else {
        console.log('Success updating Event');
        socket.emit('Update success!')  or   res.send(...);
    });
});

Assuming both userId and eventId are known from the start, the solution B seems obviously faster. Anyway, in both cases, how to make sure to perform a WRITE operation on the database only if ALL write operations were a success ?

Does the fact that i have to do this mean that my schema weren't well designed, and I should merge informations?

Thanks for your replies


Solution

  • You can use BulkOperations and do something like this:

    var bulk = db.items.initializeUnorderedBulkOp();
    bulk.find( { status: "D" } ).update( { $set: { status: "I", points: "0" } } );
    bulk.find( { item: null } ).update( { $set: { item: "TBD" } } );
    bulk.execute();
    

    Reference: http://docs.mongodb.org/manual/reference/method/Bulk.find.update/

    bulk.execute(); will return a BulkWriteResult that contains the result of the bulk operations and, in this case, the nModified documents: http://docs.mongodb.org/manual/reference/method/BulkWriteResult/#BulkWriteResult

    However, I think there is no way to run Bulk operations from mongoose since the release of MongoDb 2.6.