rsilva rsilva - 2 months ago 11
Node.js Question

async.map not working as expected

I am trying to loop though a collection and append an array of objects from a related collection. The result I am getting does not contain that array.
Can anyone help me spot the issue?

The model relationship is Page has many questions.

Question Schema:

var mongoose = require('mongoose'),
Schema = mongoose.Schema;

var questionSchema = new Schema({
_poll : { type: Schema.Types.ObjectId, ref: 'Poll' },
_page : { type: Schema.Types.ObjectId, ref: 'Page' },
type : { type : String, required: true },
title : { type : String, required: true },
required : { type : Boolean },
help_text : { type : String },
},
{ timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
});

mongoose.model('Question', questionSchema);


Page Schema:

var mongoose = require('mongoose'),
Schema = mongoose.Schema;

var pageSchema = new Schema({
_poll : { type: Schema.Types.ObjectId, ref: 'Poll' },
title : { type : String, required: true },
intro : { type : String },
list_style_type : { type : String },
},
{ timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' }
});

mongoose.model('Page', pageSchema);


Route

index: function(req, res, next){

Poll.findOne({_id: req.params.poll_id}, function(err, poll){
if(err) return next(err);

Page.find({_poll: poll.id}, function(err, pages){
if(err) return next(err);

async.map(pages, function(p, done) {
Question.find({_page: p._id}, function(err, q){
if(err) return next(err);
p.questions = q; // <-- SHOULDN'T THIS WORK? //
done(null, pages);
});
}, function(err, result) {
if(err) return next(err);
res.status(200).json(pages);
})

});
});


},

Result I am getting:

[
{
_id: "57d960fb569dc4101a83525e",
updated_at: "2016-09-14T14:38:51.113Z",
created_at: "2016-09-14T14:38:51.113Z",
_poll: "57c88775992af4c84f99c5d0",
title: "test section",
list_style_type: "lower-roman",
__v: 0
},
{
_id: "57d9691e22eb81583e20a1c1",
updated_at: "2016-09-14T15:13:34.244Z",
created_at: "2016-09-14T15:13:34.244Z",
_poll: "57c88775992af4c84f99c5d0",
title: "this is a new page",
list_style_type: "lower-roman",
intro: "jkc hcsad",
__v: 0
},
{
_id: "57d9a97d1e7863b81f9e4d0e",
updated_at: "2016-09-14T19:48:13.816Z",
created_at: "2016-09-14T19:48:13.816Z",
_poll: "57c88775992af4c84f99c5d0",
title: "Consequatur Vero necessitatibus consequatur hic",
list_style_type: "upper-latin",
intro: "Rem laboris est omnis ducimus, minim autem itaque minim dolore ea odio aliqua. Autem qui id, sit nulla id.",
__v: 0
},
{
_id: "57dab7d7f54387d41d976614",
updated_at: "2016-09-15T15:01:44.001Z",
created_at: "2016-09-15T15:01:44.001Z",
_poll: "57c88775992af4c84f99c5d0",
title: "This is a new page",
list_style_type: "lower-roman",
intro: "cjksahc dsa",
__v: 0
}
]


I expected the returned objects to contain an the array "questions" but somehow it is not there.

Thank you in advance!!

Answer

Maybe in your "Route" code, wrong variables passed to the callback. I think done(null, pages) should be done(null, p) and res.status(200).json(pages) should be res.status(200).json(result).

And because mongoose ignores fields that does not exist in the schema, questions would not appear in your result. In your "Route" code, p is a mongoose document and you can convert it into a plain javascript object by .toObject().

So maybe you can get results with questions by replacing your code like:

async.map(pages, function(p, done) {
  Question.find({_page: p._id}, function(err, q){
    if(err) return next(err);
    p = p.toObject();  // convert a mongoose document into a javascript object
    p.questions = q;
    done(null, p);  // modified 'pages' -> 'p'
  });
}, function(err, result) {
  if(err) return next(err);
  res.status(200).json(result);  // modified 'pages' -> 'result'
})
Comments