Search code examples
node.jsmongodbmongoosemongoose-populate

Mongoose multiple deep populates


Say, I have Manager schema:

{
    name: { type: String },
    clients: [{ type: Mongoose.Schema.ObjectId, ref: 'Client'}]
}

And, I have Client schema:

{
    name  : { type String },
    cars  : [{ type: Mongoose.Schema.ObjectId, ref: 'Car' }],
    houses: [{ type: Mongoose.Schema.ObjectId, ref: 'House' }]
}

And Car and House as well (their structure is not important for the matter. How do I deep populate multiple Client's fields in the single .populate() call?

What have I tried:

Manager.find()
    .populate({
         path: 'users',
         populate: { path: 'cars' },
         populate: { path: 'houses' }
    });

and it would truly surprise me if it worked (as I overwrite previously declared populate key passed to the .populate() method). My example obviously returns populated houses field per user - the one which comes last. Honestly, no idea, nothing in the docs either. Is it even supported? I know it is for 'shallow' populate, based on my example:

User.populate('cars')
    .populate('houses')

What about the deep one?


Solution

  • 1) Pass an array of objects with properties to be populated:

    Manager.find()
        .populate({
             path    : 'users',
             populate: [
                 { path: 'cars' },
                 { path: 'houses' }
             ]
        });
    

    This solution enables to use deep populate to its full extent. Consider:

    Manager.find()
        .populate({
             path    : 'users',
             populate: [
                 { path: 'cars' },
                 { 
                    path    : 'houses',
                    populate: {
                        path    : 'rooms',
                        populate: 'windows'
                    }
                 }
             ]
        });
    

    2) Pass string of space-delimited collections to be populated:

    Manager.find()
        .populate({
             path    : 'users',
             populate: 'cars houses'
        });