Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop with asynchronous callbacks in mongoose/mongodb/node

I am new to nodejs/mongo/mongoose and i am trying to do a very simple thing. I have the following schemas:

var authorSchema = mongoose.Schema({
    name: String,        
});
Author = mongoose.model('Author', authorSchema);

var bookSchema = mongoose.Schema({
    title: String,        
    isbn: String,
    pages: Number,        
    author: { type : mongoose.Schema.ObjectId, ref : 'Author', index: true }
});
Book = mongoose.model('Book', bookSchema);

I want to create a list of authors with id, name and book count for each author. I have something like this:

exports.author_list = function(req, res){
    Author.find({}, function (err, authors){
        var author_array = Array();
        for (var i=0;i<authors.length;i++){
            var author_obj = new Object();
            author_obj.id = authors[i]._id;
            author_obj.name = authors[i].name;
            author_obj.count = 0; //here is the problem 
            author_array[i] = author_obj;
        }
        res.writeHead(200, { 'Content-Type': 'application/json' });
        res.write(JSON.stringify({ authors: author_array }));
        res.end();

    });
}

I know how to do a query for the count. My problem is how to do a loop of the authors and populate the output with asynchronous callbacks. What is the proper way to implement this in nodejs fashion?

Thanks

like image 350
gtsouk Avatar asked Aug 09 '26 02:08

gtsouk


1 Answers

I think you'd want to use something like async to coordinate those requests; map() seems to be a good choice:

Author.find({}, function (err, authors) {
  async.map(authors, function(author, done) {
    Book.count({author: author._id}, function(err, count) {
      if (err)
        done(err);
      else
      {
        done(null, {
          id    : author._id,
          name  : author.name,
          count : count
        });
      }           
    });
  }, function(err, author_array) {
    if (err)
    {
      // handle error
    }
    else
    { 
      /*
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.write(JSON.stringify({ authors: author_array }));
      res.end();
      */
      // Shorter:
      res.json(author_array);
    }
  });
});
like image 196
robertklep Avatar answered Aug 11 '26 18:08

robertklep



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!