flamelite
flamelite

Reputation: 2854

Nested query Synchronization in mongodb

I have following two collection:

1) Users: {name: xyz,
         email:[email protected]}
2) Posts: {_id: 12345678,
        time:asdfg,
        authEmail:[email protected],
        description: asdigligvilud}

Here i want to get the details of each post along with the corresponding name of author id. So i wrote query like this:

// get all the posts
Posts.find((err, posts)=> {

  if (err) { next(err) };
  var data = Array();
  var count = 0;
  var len = posts.length;
  // function to check the end of inner queries
  var checkloop = function(){
    count++;
    if(count===len)
        return res.json({result:data,
                msg:'success'});
    }

  for(var i=0;i<len;i++){

    Users.findOne({email:posts[count].authEmail},(err,usr)=>{

    if(usr){
        var item = {
                    'authorName':usr.name?
                    'email':usr.email,
                    'postDesc':posts[count].desc,
                    'creationTime':posts[count].time
                    }
        data.push(item);

        }
        checkloop();
    });

    }

});

But i am getting same result for each iterations that is the post deatils and author id corresponding to the very first loop that is posts[0] only. So i think its because of asynchronous nature of queries. Is there any standard way to make such query in mongodb or do i need to change my callback method?

Thanks in advance.

Upvotes: 0

Views: 235

Answers (1)

kevinAlbs
kevinAlbs

Reputation: 1124

I believe the issue you had was because count inside the for loop probably was meant to be i. In addition, each loop iteration captures the same variable i in the Users.findOne callback, but the callback should be able to refer to the post that was queried. Without making much changes, I think this can work with using forEach over the returned posts like below:

// get all the posts
Posts.find((err, posts)=> {

  if (err) { next(err) };
  var data = Array();
  var count = 0;
  var len = posts.length;
  // function to check the end of inner queries
  var checkloop = function(){
    count++;
    if(count===len)
        return res.json({result:data,
                msg:'success'});
    }

  posts.forEach((post) => {
      Users.findOne({email:post.authEmail},(err,usr)=>{
        if(usr){
            var item = {
                        'authorName':usr.name?
                        'email':usr.email,
                        'postDesc':post.desc,
                        'creationTime':post.time
                        }
            data.push(item);

            }
            checkloop();
        }
      });
  });

Upvotes: 1

Related Questions