node.js - Why is MongoDB ignoring some of my updates? -


i've been building application in node.js using native mongodb driver - includes contacts, , when user accepts contact, should remove "pending" , "sent" contacts, add "contacts".

example code , documents:

    /* ============================= user "john" ============================= {   username: "john",   contacts: ["jim"],   pending_contacts: ["bob"] }  ============================= user "bob" ============================= {   username: "bob",   contacts: ["dave"],   sent_contacts: ["john"] }  ============================= should happen ============================= {   username: "bob",   contacts: ["dave", "john"],   sent_contacts: [] }, {   username: "john",   contacts: ["jim", "bob"],   pending_contacts: [] }  ============================= happens ============================= {   username: "john",   contacts: ["jim", "bob"],   pending_contacts: ["bob"] }, {   username: "bob",   contacts: ["dave", "john"],   sent_contacts: ["john"] }  */    var col = this.db.collection('users');   var contact = "bob", username = "john";   var = [contact, username];   var finishcount = 0;   // finish run 3 times before callback   function finish(name) {     console.log(name, ' has finished');     finishcount++;     if(finishcount<3) return;     callback(false, null);   }   // run if there's error   function failed(err) {     callback(err, null)   }   console.log('removing %s , %s pending , sent', username, contact)   col.update(     {username: { $in: }},     {       $pullall: {         sent_contacts: who,         pending_contacts:       }     }, {multi: 1},     function(err,data) {       if(err) return failed(err);       finish('remove_contacts');     }   );   col.update(     {username: username}, {$addtoset: {contacts: contact}},     function(err,res) {       if(err) return failed(err);       console.log('added 1');       finish('add_to_user');     }   );   col.update(     {username: contact}, {$addtoset: {contacts: username}},     function(err,res) {       if(err) return failed(err);       console.log('added 2');       finish('add_to_contact');     }   ); 

the first update removes contact , owner each-others pending/sent list, second , third update add owner contact's contact list , vice versa.

the issue is, final result appears if removal never happened, though removal query works fine itself. don't know if problem mongodb (or if it's intended), or if it's issue driver, hope can @ least clarify me.

note: yes know run asynchronously. running them 1 after other putting each update in previous callback not make difference. before complains how awful code looks, had set within async.js removed code sample ensure asyn.cjs not responsible issues.

using node native driver works me every time:

var mongodb = require('mongodb'),     async = require('async'),     mongoclient = mongodb.mongoclient;  var user = "john",     contact  = "bob";  var contactslist = [   {     "username": "john",     "contacts": [       "jim"     ],     "pending_contacts": [       "bob"     ]   },   {     "username": "bob",     "contacts": [       "dave"     ],     "sent_contacts": [       "john"     ]   } ];  mongoclient.connect('mongodb://localhost/test',function(err,db) {    var coll = db.collection("contacts");    async.series(     [       // wipe clean       function(callback) {         coll.remove({},callback)       },        // init collection       function(callback) {         async.each(contactslist,function(contact,callback) {           coll.insert(contact,callback);         },callback);       },        // updates       function(callback) {         // init batch         var bulk = coll.initializeorderedbulkop();          // add user , pull pending         bulk.find({           "username": user,           "contacts": { "$ne": contact },         }).updateone({           "$push": { "contacts": contact },           "$pull": { "pending_contacts": contact }         });          // add contact , pull sent         bulk.find({           "username": contact,           "contacts": { "$ne": user },           "sent_contacts": user         }).updateone({           "$push": { "contacts": user },           "$pull": { "sent_contacts": user }         });          // execute         bulk.execute(function(err,response) {           console.log( response.tojson() );           callback(err);         });        },        // list collection       function(callback) {         coll.find({}).toarray(function(err,results) {           console.log(results);           callback(err);         });       }      ],     function(err) {       if (err) throw err;       db.close();     }    );  }); 

and output:

{ ok: 1,   writeerrors: [],   writeconcernerrors: [],   insertedids: [],   ninserted: 0,   nupserted: 0,   nmatched: 2,   nmodified: 2,   nremoved: 0,   upserted: [] } [ { _id: 55b0c16934fadce812cdcf9d,     username: 'john',     contacts: [ 'jim', 'bob' ],     pending_contacts: [] },   { _id: 55b0c16934fadce812cdcf9e,     username: 'bob',     contacts: [ 'dave', 'john' ],     sent_contacts: [] } ] 

improvements here use bulk operations api , send updates @ once server , single response. note use of operators in updates , query selection well.

simply put, know "user" "contact" accepting. contact accepted "pending" , contact have user in "sent".

these simple $push , $pull operations on either array appropriate. rather using $addtoset here, query conditions make sure expected values present when performing update. preserves "order" $addtoset can not guarantee, because it's "set", un-ordered.

one send server , 1 callback response, leaving both users updated correctly. makes more sense sending multiple updates , waiting callback response each.

anyhow, complete self contained listing 2 named dependencies, can run , confirm results.


when "complete , self contained" means start new project , run code. here's complete instruction:

mkdir sample cd sample npm init npm install mongodb --save npm install async --save 

then create file code listing in folder, test.js , run:

node test.js 

Comments

Popular posts from this blog

qt - Using float or double for own QML classes -

Create Outlook appointment via C# .Net -

ios - Swift Array Resetting Itself -