Search code examples
node.jsmongodbmongoosemongoose-populate

Populate subdocument array field with Mongoose


I know this question has been asked before, but after hours of research I have tried several ways to solve my problem without success.

Schema

    const ValuationsSchema = new Schema(
      {
        value: { type: Number, required: true, min: 0, max: 5 },
        author: {
          type: Schema.Types.ObjectId,
          refPath: "fromModel",
          required: true,
        },
        fromModel: {
          type: String,
          required: true,
          enum: ["usertype1", "usertype2", "usertype3"],
          trim: true,
        },
      },
      {
        timestamps: true,
      }
    );
    
    const UserSchema = new Schema(
      {
        name: { type: String, required: true, trim: true },
        valuations: [ValuationsSchema],
      },
      {
        timestamps: true,
      }
    );

What am I trying to do

I am trying to populate the author field of ValuationsSchema, in the valuations array of a user.

Sample data

Result expected

{
  _id: 5f1ef9f6039fea10c437939c,
  name: 'Jose Maria',
  createdAt: 2020-07-27T15:59:50.529Z,
  updatedAt: 2020-08-01T15:34:47.414Z,
  valuations: [
    {
      _id: 5f258b973c0ac544869c0434,
      value: 5,
      author: Object,
      fromModel: 'particular',
      createdAt: 2020-08-01T15:34:47.414Z,
      updatedAt: 2020-08-01T15:34:47.414Z
    }
  ]
}

Result gotten

{
  _id: 5f1ef9f6039fea10c437939c,
  name: 'Jose Maria',
  createdAt: 2020-07-27T15:59:50.529Z,
  updatedAt: 2020-08-01T15:34:47.414Z,
  valuations: [
    {
      _id: 5f258b973c0ac544869c0434,
      value: 5,
      author: 5f1edaa83ce7cf44a2bd8a9a,
      fromModel: 'particular',
      createdAt: 2020-08-01T15:34:47.414Z,
      updatedAt: 2020-08-01T15:34:47.414Z
    }
  ]
}

Already tried solutions

At the moment I manually populated the field, but as it is a good practice, I am trying to use the API when possible.

As far as I am concerned executing this should get the job done, but it doesn't.

    await user.populate("valuations.author").execPopulate();

Also tried this without luck:

    await user.populate({
                        path: "valuations",
                        populate: {
                          path: "author",
                        },
                      }).execPopulate();

Tried the deepPopulate package too, but yet same result.


Solution

  • The refPath should be from parent level valuations.fromModel,

    • Change it in your schema,
    author: {
        type: Schema.Types.ObjectId,
        refPath: "valuations.fromModel",
        required: true,
    }
    
    • Single document wise population,
    let user = await User.find();
    let user1 = await user[0].populate("valuations.author").execPopulate();
    
    • All documents population
    let users = await User.find().populate("valuations.author").execPopulate();
    

    Note: There is a bug #6913 in mongoose version 5.2.9, refPath not working in nested arrays, Make sure you have installed latest version.