mongoose: Can't make nested populate in new mongoose 3.6rc0

I have the following schemas:

var DocumentSchema = new Schema({
  title    : {type: String},
  emails   : [{type: ObjectId, ref: 'Emails'}]
});

var EmailSchema = new Schema({
  title    : {type: String},
  tags     : [{type: ObjectId, ref: 'Tags'}]
});

var TagSchema = new Schema({
  title    : {type: String}    
});

I want to find a document with populated ‘emails’ and tags. When I try this:

Document.findById(ObjectId('...'))
  populate('emails.tags')
  .exec(function (err, document) {

  });

I get the error:

Caught exception: TypeError: Cannot call method 'path' of undefined

About this issue

  • Original URL
  • State: closed
  • Created 11 years ago
  • Comments: 19

Most upvoted comments

@yangsu you are correct. Though there is another way. Either specify the model that should be used for population in the options to User.populate or use the Phone model directly:


BlogPost.find({ tags: 'fun' }).lean().populate('author').exec(function (err, docs) {
  assert.ifError(err);

  User.populate(docs, {
    path: 'author.phone',
    select: 'name',
    model: Phone // <== We are populating phones so we need to use the correct model, not User
  }, callback);

  // or use the model directly

  Phone.populate(docs, {
    path: 'author.phone',
    select: 'name',
  }, callback);

This seems clunky. We should be able to do better with this in a future release. If the documents being populated are mongoose documents (opposed to plain objects) we could possibly use it’s related schema to determine which Model to use. Won’t work for plain objects of course.

As the metadata for population is present in the ref property, shouldnt the libary be able to automatically guess the correct model for population?

BlogPost.find({ tags: ‘fun’ }).lean().populate(‘author’).exec(function (err, docs) { assert.ifError(err);

User.populate(docs, { path: ‘author.phone’, select: ‘name’, model: Phone // <== We are populating phones so we need to use the correct model, not User }, callback);

// or use the model directly

Phone.populate(docs, { path: ‘author.phone’, select: ‘name’, }, callback);