How do I properly use chain populate method in my node application?

Viewed 229

I am building a blog application using node.js and react. I am using MongoDB and would like to use the Mongoose .populate method to fetch data among collections. I have three collections so far: Post, User and Category collections. I have been able to use the .populate() method to get username from the User Schema model and point it to the Post Schema model. This way, users can make post and their username properly linked to them. Now, I want users to create category for the posts they create and I want that category to be associated with the specific post that the user made the post on. I have referenced the Category Schema model to the Post model and used the populate() method. After user creates post, the category doesn't show on the post. The category creation works well. But category is not populating. Seems I didn't do it rightly. Here is my code:

Post Schema Model

     const mongoose = require("mongoose"); //import mongoose
     const Schema = mongoose.Schema;

     const PostSchema = new mongoose.Schema(
    {
       
        title:{
            type: String,
            required: true,
            unique: true
        },
        description:{
            type: String,
            required: true, 
        },
        postPhoto:{
            type: String,
            required:false,
        },
       username:{
            type: Schema.Types.ObjectId, 
            ref: 'User'
        },
        categories:{
           type: Schema.Types.ObjectId, //referenced Category Schema Model
            ref: 'Category"'
            
        },
       
    }, {timestamps: true}
    );
    //exporting this schema
    module.exports = mongoose.model("Post", PostSchema); //the module name is "Post"

Category Schema Model

    const mongoose = require("mongoose"); //import mongoose to be used
    const Schema = mongoose.Schema;

     const CategorySchema = new mongoose.Schema(
    {
       catname:{
           type: String, 
            required: false,
       }
       
      }, {timestamps: true}
      );
     //exporting this schema
     module.exports = mongoose.model("Category", CategorySchema); //the module name is "Post"

Post route

     router.get("/:id", async(req, res)=>{
     try{
        const post = await Post.findById(req.params.id).populate('username').populate(' categories')
         
       
        
        //const post = await Post.findById(req.params.id );
        
     
        res.status(200).json(post)

      }catch(err){
        res.status(500).json(err)
      }
      })

Category route

    //creating catergory logic

    router.post("/", async (req, res) =>{
    const newCat = new Category(req.body);//we create a new category for the database
        
    try{
        const savedCategory = await newCat.save();//we need to try and catch the new category and  save it
        res.status(200).json(savedCategory)
    }catch(err){
        res.status(500).json(err)
    }
    })
2 Answers

You have a typo in your query. You have an extra space when populating categories.

Change this:

.populate(' categories')

with this:

.populate('categories')

The Schema you have written has a slight problem,

the field name is categories which implies that it should be an array of category object IDs

for example the post can have "Tech", "Python" etc...

change the categories field in the Post schema like this

categories:[{ type: mongoose.Schema.Types.ObjectId, ref: "Category" }]

The reason you are not able to see the categories when you populate them in the GET route for post is because, the logic you have written is for add new category so this never says which category is this post associated to? You can add a new route for adding catgories to the post logic like this

//? Adding category to post logic
router.post("/:category_id/:post_id", async (req, res) =>{
    
 try{
    const {category_id, post_id} = req.params//? get the category Id 
                        //?and Post Id from the route params.

    //? Find the post you want to add the category 
    await Post.findByIdAndUpdate(
     {_id:post_id},
     { $push: { categories: category_id } },
     {new:true},
    )
    res.status(200).json(savedCategory)
 }catch(err){
    res.status(500).json(err)
 }
})

this logic will add the categoryId into the categories field in the post.

Now you query for post and populate the categories fields, you will get the categories the post is associated to

Related