Home > OS >  How to deep populate with self-referential model Mongoose
How to deep populate with self-referential model Mongoose

Time:09-01

I'm trying to populate across multiple levels using the following fields firstly from an Article model:

 comments: [
            {
                type: Schema.Types.ObjectId,
                 ref: "Comment"
            
            }
        ]

and then from the Comment model:

  replies : [ {
        type: Schema.Types.ObjectId,
         ref: "Comment"
     }]

I have referred to the Mongoose docs on populating across multiple levels and numerous other resources to create my query:

    const getArticle = async (req, res) => {
  const slug = { slug: req.params.slug};
  const page = "Article";
   let article = await Article.findOne(slug)
    .populate({
      path: "comments",
      model: "Comment",
      options: {
        sort: { date: -1}
      },
      populate:{
        path: "replies",
        model: "Comment",
        options: {
          sort: { date: -1}
        }
      }
    })

  console.log("articlePop:", article);
  res.render("show", { page, article });
};

When I check the documents in Mongosh everything appears as it should with the correct ref _ids in place, however the query does not populate the replies field:

     {
  _id: new ObjectId("630f83777b023e0af292dd4a"),
  username: 'noffler',
  date: '31/08/2022, 16:51:19',
  title: 'the napoleonic wars',
  article: 'the return of Napoleon',
  likes: 0,
  dislikes: 0,
  comments: [
    {
      _id: new ObjectId("630f83917b023e0af292dd50"),
      username: 'noffler',
      date: '31/08/2022, 16:51:45',
      comment: 'some say money is bad for the soul',
      likes: 0,
      dislikes: 0,
      replies: [Array],
      __v: 0
    }
  ],
  slug: 'the-napoleonic-wars',
  __v: 0
}

I would be really grateful if anyone could point me in the right direction. Kind Regards.

CodePudding user response:

maybe 1 - you missed add exec function at the end

let article = await Article.findOne(slug)
  .populate({
    path: "comments",
    model: "Comment",
    options: {
      sort: { date: -1}
    },
    populate:{
      path: "replies",
      model: "Comment",
      options: {
        sort: { date: -1}
      }
    }
  }).exec(function(err, docs) {});

or 2 - you should add [] around replies object

   let article = await Article.findOne(slug)
    .populate({
      path: "comments",
      model: "Comment",
      options: {
        sort: { date: -1}
      },
      populate:[{
        path: "replies",
        model: "Comment",
        options: {
          sort: { date: -1}
        }
      }]
    })

I hope it will be help you

CodePudding user response:

Why don't you consider using MongoDB's aggregation?

I would highly recommend it

  • Related