0

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.

1
  • Make one query with $in instead of a loop. Users.find({ 'emai'l: { '$in': posts.map(p => p.authEmail) } },(err,users) => { .... No need for looping async calls, and no mess. Commented Aug 6, 2017 at 22:31

1 Answer 1

1

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();
        }
      });
  });
Sign up to request clarification or add additional context in comments.

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.