I've:
User
model (from UserSchema
)Specialty
model (from SpecialtySchema
)Session
model (from SessionSchema
)User has reference field specialities
:
specialities: [{ type: Schema.Types.ObjectId, ref: 'Specialty' }]
Session has reference field provider
:
provider: { type: Schema.Types.ObjectId, ref: 'Session' }
I want to get list of sessions with populated provider
(User) and deep populated specialities
over provider
.
I'm doing following:
Session
.find()
.populate({
path: 'provider',
model: 'User',
populate: {
path: 'specialities',
model: 'Specialty',
}
})
However the results always return an array of IDS (when I try to access them by provider.specialities
instead of the populated version.
Is specialities a keyword?
I don't know why it's like not populating at all.
Quick solution is to use mongoose-deep-populate
In every schema attach it as plugin:
const deepPopulate = require('mongoose-deep-populate')(mongoose);
SessionSchema.plugin(deepPopulate, {
whitelist: ['provider', 'provider.specialities']
});
and then use it like this:
const Session = mongoose.model('Session');
cons user = await Session.findById(id here)
.deepPopulate(['provider', 'provider.specialities']);
Due to possible performance issues I don't recommend to do deep populate.
Better to try to re-think Your data.
Also I cannot imagine use case for it.
Maybe You just want to show user list with specialities?
What about just to do 2 api calls from frontend:
1st for taking sessions and taking provider ids (ex.: GET /sessions),
2nd for taking users with populated specialities (ex.: GET /users?ids=first-id,second-id...)
or:
let sessions = await Session.find();
let providerIds = sessions.map(session => session.provider);
let users = await User.find({_id: providerIds}).populate('specialities');
sessions = sessions.map(session => {
session.provider = users.find(user => user._id == session.provider);
return session;
});