0

i am having trouble saving a new record to mongoDB. i am pretty sure there is something i am using in my code that i don't fully understand and i was hoping someone might be able to help.

i am trying to save a new record to mongoDB for each of the cats. this code is for node.js

for(var x = 0; x < (cats.length - 1); x++){
    if (!blocked){
      console.log("x = "+x);
      var memberMessage = new Message();
      memberMessage.message = message.message;
      memberMessage.recipient = room[x].userId;

      memberMessage.save(function(err){
        if (err) console.log(err);

        console.log(memberMessage + " saved for "+cats[x].name);
      });
    }
  });
}

i log the value of "cats" before the loop and i do get all the names i expect so i would think that looping through the array it would store a new record for each loop.

what seems to happen is that when i look ta the the database, it seems to have only saved for the last record for every loop cycle. i don't know how/why it would be doing that.

any help on this is appreciated because I'm new to node.js and mongoDB.

thanks.

1
  • use foreach , this is will work fine Commented Jan 19, 2015 at 8:26

2 Answers 2

5

That's because the save is actually a I/O operation which is Async. Now, the for loop is actually sync. Think of it this way: your JS engine serially executes each line it sees. Assume these lines are kept one-after-another on a stack. When it comes to the save, it keeps it aside on a different stack (as it is an I/O operation, and thus would take time) and goes ahead with the rest of the loop. It so turns out that the engine would only check this new stack after it has completed every line on the older one. Therefore, the value of the variable cats will be the last item in the array. Thus, only the last value is saved.

To fight this tragedy, you can use mutiple methods:

  1. Closures - Read More
  2. Promises - Read More. There is a sweet library which promisifies the mongo driver to make it easier to work with.
  3. Generators, etc. - Read More. Not ready for primetime yet.

Note about #2 - I'm not a contributor of the project, but do work with the author. I've been using the library for well over an year now, and it's fast and awesome!

Sign up to request clarification or add additional context in comments.

Comments

2

You can use a batch create feature from mongoose:

var messages = [];
for(var x = 0; x < (cats.length - 1); x++) {
    if (!blocked) {
       var message = new Message();
       message.message = message.message;
       message.recipient = room[x].userId;
       messages.push(message);
    } 
}

Message.create(messages, function (err) {
  if (err) // ...
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.