Mongoose Populate not working

Similar to CodyBugstein's answer, I'm posting why it wasn't working in my case, even though it's not the same case as OP's.

I was trying to populate the "pro" field of my schema in a .post('save') hook, as so:

mySchema.post('save', function(doc, next) {
    console.log(doc.pro); // Expected to log ObjectID
    doc.populate("pro"); // Populate field
    console.log(doc.pro); // Expected to log actual pro document
}

However, the 2nd console.log was also logging the ObjectID instead of the doc.

After struggling with this for a solid hour and trying different approaches, I found out that all I had to do was use promises and call execPopulate() so that it returned a fully-fledged promise. I used async/await but you could use .then too:

mySchema.post('save', async function(doc, next) {
    console.log(doc.pro); // Expected to log ObjectID
    await doc.populate("pro").execPopulate(); // Populate field
    console.log(doc.pro); // Expected to log actual pro document
}

This way, the 2nd console.log did log the entire pro doc as expected :)


By default, Mongoose pluralizes the model name to come up with the name of the collection, so Mongoose is looking in the avs collection instead of av.

You can explicitly set the collection name by passing that as the third parameter to model:

var Av = mongoose.model('Av', AvSchema, 'av');

I had the same issue but none of the answers worked for me.

I wanted to populate a document after it was queried.

This didn't work:

// IIFE for async/await
( async() => {

    var user = await User.findOne( { _id } );

    await user.populate( 'comments' ); // Doesn't work

} );

The Mongoose Documentation explains that when calling .populate() without a callback it won't be executed. Instead you need to use .populate().execPopulate():

// IIFE for async/await
( async() => {

    var user = await User.findOne( { _id } );

    await user.populate( 'comments' ).execPopulate(); // Works as expected

} );