-2

I've:

  1. User model (from UserSchema)
  2. Specialty model (from SpecialtySchema)
  3. 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.

num8er
  • 18,604
  • 3
  • 43
  • 57
DarkArtistry
  • 434
  • 1
  • 6
  • 22
  • Please paste your schemas – kit Jul 04 '18 at 15:53
  • Where is deep population? Simply `mongoose.model('User').findById(id here).populate('specialities')...` and so on... – num8er Jul 05 '18 at 01:02
  • i thought for mongoose ver 4 on wards you could deep populate like this ? .populate({ path: 'provider', model: 'User', populate: { path: 'specialities', model: 'Specialty', } }) – DarkArtistry Jul 05 '18 at 01:04
  • @num8er that works, for normal population, but when i try to deep populate a Session model's provider's specialities it does not work – DarkArtistry Jul 05 '18 at 01:05
  • @DarkArtistry can You add Your code where You `try to deep populate a Session model's provider's specialities` ? – num8er Jul 05 '18 at 01:07
  • @num8er yeah im trying to do that, to deep populate a Session model's provider's specialities. The deep population codes are right at the top – DarkArtistry Jul 05 '18 at 01:08
  • @DarkArtistry You mean You keep an object in `req.session.user` and want to populate specialities? You have to show how You get that session model instance – num8er Jul 05 '18 at 01:09
  • i did Session.find() .populate({ path: 'provider', model: 'User', populate: { path: 'specialities', model: 'Specialty', } }) – DarkArtistry Jul 05 '18 at 01:10

1 Answers1

0

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;
});
num8er
  • 18,604
  • 3
  • 43
  • 57