Mongoose document.populate() is not working

Viewed 7465

I am using a pretty simple Node/Mongo/Express setup and am trying to populate referenced documents. Consider my schemas for "Courses" which contain "Weeks":

// define the schema for our user model
var courseSchema = mongoose.Schema({

    teachers        : { type: [String], required: true  },
    description     : { type: String              },
    previous_course : { type: Schema.Types.ObjectId, ref: 'Course'},
    next_course     : { type: Schema.Types.ObjectId, ref: 'Course'},
    weeks           : { type: [Schema.Types.ObjectId], ref: 'Week'},
    title           : { type: String              }

});

// create the model for Course and expose it to our app
module.exports = mongoose.model('Course', courseSchema);

I specifically want to populate my array of weeks (though when I changed the schema to be a single week, populate() still didn't work).

Here is my schema for a Week (which a Course has multiple of):

var weekSchema = mongoose.Schema({

    ordinal_number  : { type: Number, required: true },
    description     : { type: String              },
    course          : { type: Schema.Types.ObjectId, ref: 'Course', required: true},
    title           : { type: String              }

});

// create the model for Week and expose it to our app
module.exports = mongoose.model('Week', weekSchema);

Here is my controller where I am trying to populate the array of weeks inside of a course. I have followed this documentation:

// Get a single course
exports.show = function(req, res) {

  // look up the course for the given id
  Course.findById(req.params.id, function (err, course) {

    // error checks
    if (err) { return res.status(500).json({ error: err }); }
    if (!course) { return res.sendStatus(404); }

    // my code works until here, I get a valid course which in my DB has weeks (I can confirm in my DB and I can console.log the referenced _id(s))

    // populate the document, return it
    course.populate('weeks', function(err, course){
      // NOTE when this object is returned, the array of weeks is empty
      return res.status(200).json(course);
    });
  };
};

I find it strange that if I remove the .populate() portion from the code, I get the correct array of _ids back. But when I add the .populate() the returned array is suddenly empty. I am very confused!

I have also tried Model population (from: http://mongoosejs.com/docs/api.html#model_Model.populate) but I get the same results.

Thanks for any advice to get my population to work!

3 Answers

below should return course with populated weeks array

exports.show = function(req, res) {
      // look up the course for the given id
      Course.findById(req.params.id)
      .populate({
        path:"weeks",
        model:"Week"
      })
      .exec(function (err, course) {
            console.log(course);
      });
    };

### update: you can populate from instance also ###

  Course.findById(req.params.id, function (err, course) {
    // error checks
    if (err) { return res.status(500).json({ error: err }); }
    if (!course) { return res.sendStatus(404); }
    // populate the document, return it
    Course.populate(course,  { path:"weeks", model:"Weeks" }, function(err, course){
      console.log(course);
    });
  });

### Update2: Perhaps even more cleanly, this worked: ###

Course.findById(req.params.id, function (err, course) {
    // error checks
    if (err) { return res.status(500).json({ error: err }); }
    if (!course) { return res.sendStatus(404); }
    // populate the document, return it
      console.log(course);
  }).populate(course,  { path:"weeks", model:"Weeks" });

here it seems like you are using course.populate() instead of Course.populate()

Use this code instead of yours,I change only one single word course.populate() to Course.populate()

In your case "course" is instance but you need to use Course(Model)

Course.findById(req.params.id, function (err, course) {

    if (err) { return res.status(500).json({ error: err }); }
    if (!course) { return res.sendStatus(404); }

   // Guys in some case below three-line does not work in that case you must comment these lines and uncomments the last three-line

    Course.populate('weeks', function(err, course){
      return res.status(200).json(course);
    });

   // Course.populate({  path:"weeks", model:"Weeks" }, function(err, course){
   //   return res.status(200).json(course);
   // });

  };
Related