Search code examples
node.jsmongodbmongoosemongoose-schemamongoose-populate

Mongoose document.populate() is not working


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!


Solution

  • 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" });