R. Erickson
R. Erickson

Reputation: 108

Unable to populate nested array

I'm fairly new to MongoDB and Mongoose and I am trying to populate a nested array without any luck.

Users have a prop called 'proceedings' which is an array of objects. Each element in that array contains some props including and array called 'forms'.

proceedings[i].forms holds refs to all the forms in the forms collection for the proceeding.

There is nothing to populate in 'proceedings' other than 'forms'. I am trying to populate the nested 'forms' array for each proceeding.

So:

User: {
  _id: ObjectId,
  proceedings: [
    {
      _id: ObjectId,
      forms: [
        ObjectId,
        ObjectId,
        ObjectId
      ]
    },
    {
      _id: ObjectId,
      forms: [
        ObjectId,
        ObjectId,
        ObjectId
      ]
    }
  ]
}

Schemas:

const formSchema = new Schema({
  userId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  },
  values: { type: mongoose.Schema.Types.Mixed }
}, { timestamps: true });

const proceedingsSchema = new Schema({
  initial_questions: {},
  forms: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Form'
    }
  ]
});

const userSchema = new Schema({
  email: {
    type: String,
    default: '',
    unique: true
  },
  password: {
    type: String,
    default: ''
  },
  sign_up_date: {
    type: Object,
    default: moment(),
    get: parseDate
  },
  proceedings: [proceedingsSchema]
}, { timestamps: true });

userSchema.set('toObject', { getters: true });
userSchema.set('toJSON', { getters: true });

export const User = mongoose.model('Users', userSchema);
export const Form = mongoose.model('Forms', formSchema);

Query:

User.findOne({ _id: id })
  .populate({
    path: 'proceedings',
    populate: {
      path: 'forms',
      model: 'Form'
    }
  })
  .exec((err, user) => {
    console.log(user.proceedings[0].forms)
  })

The result is an array of ObjectId's instead of the populated forms in their place.

Any help greatly appreciated.

Mongoose - v5.0.1

Upvotes: 0

Views: 130

Answers (1)

R. Erickson
R. Erickson

Reputation: 108

After thinking more about @dprogramz comment I decided to move the proceedings to their own collection. This query now works:

 Proceeding.find({ userId: id })
    .populate({
      path: 'forms',
      model: 'Forms'
    })
    .exec((err, proceedings) => {
      if (err) {
        logger.error(err.message);
        return res.send({ error: err.message });
      }

      if (!proceedings) {
        return res.send({ error: 'No such proceedings' });
      }

      return res.send({ ok: { proceedings, proceedingId: proceedings[proceedings.length - 1]._id }});
    });

Upvotes: 2

Related Questions