javascriptmongodbmongoosemongodb-querymongoose-populate

Populate different fields in a mongoose query


I have the following models:

User:

const userSchema = new mongoose.Schema(
  {
    name: { type: String, min: 3, max: 20, required: true },
    email: { type: String, required: true, unique: true },
    password: { type: String, min: 3, max: 50, required: true },
    blogs: [
      {
        type: mongoose.SchemaTypes.ObjectId,
        type: String,
        ref: "Blog",
        required: false,
        default: [],
      },
    ],
    comments: [
      {
        type: mongoose.SchemaTypes.ObjectId,
        type: String,
        ref: "Comment",
        required: false,
        default: [],
      },
    ],
  },
  { timestamps: true, collection: "users" }
);

Comment:

const commentSchema = new mongoose.Schema(
  {
    title: { type: String, min: 1, max: 25, required: true },
    content: { type: String, min: 1, max: 250, required: true },
    author: {
      type: mongoose.SchemaTypes.ObjectId,
      ref: "User",
      required: true,
    },
    blogRef: { type: mongoose.SchemaTypes.ObjectId, ref: "Blog" },
  },
  { timestamps: true, collection: "comments" }
);

Blog:

const blogSchema = new mongoose.Schema(
  {
    title: { type: String, min: 3, max: 20, required: true },
    content: { type: String, required: true },
    likes: { type: Number, required: true, default: 0 },
    author: { type: mongoose.SchemaTypes.ObjectId, ref: "User" },
    comments: [
      { type: mongoose.SchemaTypes.ObjectId, ref: "Comment", default: [] },
    ],
  },
  { timestamps: true, collection: "blogs" }
);

I want to query all the blogs and populate their author field, comment field, and the author field in the comment. I tried doing it like this:

const blogs = await Blog.find()
  .populate("author")
  .populate("comments")
  .populate("author");

but it didn't work, what am I doing wrong? If you have any suggestion please let me know.


Solution

  • You have to nest the populate like so:

    const blogs = await Blog.find()
      .populate('author')
      .populate({
          path: 'comments',
          populate: { 
             path: 'author' 
          }
       });
    

    If the models have not been registered yet you can explicitly pass them like so:

    const blogs = await Blog.find()
      .populate({path: 'author', model: User})
      .populate({
          path: 'comments', model: Comment,
          populate: { 
             path: 'author', model: User 
          }
       });