s_curry_s
s_curry_s

Reputation: 3432

Mongoose For each element in loop

I am trying to loop through an array and add the items in the array to a mongodb database if it doesnt exist already. Inside the loop I try to query my database if the next element in the array is already in the database. However inside the callback function, console.log always returns the last element of the array.

for(var j = 0 ; j < req.body.array.length; j++ ){
    var currenttag = req.body.array[j];
    Tag.findOne({tagname : currenttag},
      function(err,tag){
        if(tag){
          console.log("tag exists");
        }
        else{
            console.log(currenttag);//returns the last tag in the array for array.length times
            var newtag  = new Tag({tagname : currenttag});
            newtag.save();
        }
      });
  }

Upvotes: 1

Views: 6437

Answers (1)

verybadalloc
verybadalloc

Reputation: 5804

I think the error is related to how closures are handled in Javascript. Please see my answer here for more details on what this means.

In your case, the event handler is getting a reference to currentTag, which is set to the last element of the loop.

To solve this, you can try to do the following:

var createTagIfMissing = function (currentTag){

Tag.findOne({tagname : currenttag},
      function(err,tag){
        if(tag){
          console.log("tag exists");
        }
        else{
            console.log(currenttag);
            var newtag  = new Tag({tagname : currenttag});
            newtag.save();
        }
      });
}

for(var j = 0 ; j < req.body.array.length; j++ ){
  createTagIfMissing(req.body.array[j]);
}

You could push this even further, and define this method as one of your Tag statics:

//In your db.js file, before mongoose.model('Tag',Tag);
Tag.statics.createTagIfMissing = function(tag){
    this.findOne //...
}

Then, in your router code:

for(var j = 0 ; j < req.body.array.length; j++ ){
  Tag.createTagIfMissing(req.body.array[j]);
}

Upvotes: 3

Related Questions