wscourge
wscourge

Reputation: 11291

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?

Upvotes: 10

Views: 10480

Answers (2)

Ahmed Shaikh
Ahmed Shaikh

Reputation: 136

This is the way to do nested population. In this case First it will populate users and then populate hobbies of user and then populate football from hobbies of user and then it will populate favourite playerNames from user -> hobbies -> football -> favouritePlayers.

Model.find()
    .populate({
         path    : 'users',
         populate: [
             { path: 'Hobbies' },
             { 
                path    : 'Football',
                populate: {
                    path    : 'favouritePlayers',
                    populate: 'playerNames'
                }
             }
         ]
    });

Upvotes: 1

wscourge
wscourge

Reputation: 11291

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'
    });

Upvotes: 22

Related Questions