1

I am trying to create new comment in my node.js application but it is returning error. I am actually trying to create the new comment under specific posts using my posts path. Here are my codes:

Comment Model

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

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

Comment routes

const router = require("express").Router()
const Comment = require("../models/Comment")

router.post("/posts/:id/comment", async (req, res) =>{
const newComment = new Comment(req.body);//we create a new category for the database
    
try{
    const savedComment = await newComment.save();
    res.status(200).json(savedComment)
}catch(err){
    res.status(500).json(err)
}
})

Index.js

const express = require("express");//creating the express server
const app = express(); //creating the application
const mongoose = require("mongoose");

app.use("/api/posts/:id", commentRoute)

If I do not target "/posts/:id/comment path and targeted comment root path "/", the comment creation works in postman. But I am trying to create the comment right inside a post using the post :id. It is not working. It is throwing this error on postman:

Postman error

<head>
<meta charset="utf-8">
<title>Error</title>
</head>

<body>
<pre>Cannot POST /api/posts/6137668b697dd2448c3f454c/comment</pre>
</body>

I attached screen shot of my postman error and setup enter image description here

kinhs
  • 175
  • 13
  • Thank you, I have corrected it – kinhs Sep 07 '21 at 14:27
  • After a quick glance, I'm wondering if it's the `/api/` prefix that's giving you trouble. The router accepts `"/posts/:id/comment"`, but is mounted at `"/api/posts/:id"` Can you confirm whether or not it's supposed to be `/api/posts/:id/comment`? – Wyck Sep 07 '21 at 14:35
  • I did add that but didn't work. I mean "/api/posts/:id/comment" didn't work either. – kinhs Sep 07 '21 at 15:26
  • The router is mounted at `/api/posts/:id` so the fix would actually be to have called `router.post("/comment", ...` to respond to `/api/posts/:id/comment` – Wyck Sep 07 '21 at 16:07

2 Answers2

0

The way you currently have your route set up, it is expecting your path to look like this:

/api/posts/:id/posts/:id/comment <--- which is not what you're wanting

When the code in your commentsRoute file gets executed, the path is already at /api/posts/:id, so your comment route just needs to check the last part of the path/comment.

Rewrite your commentRoute to look more like this:

// ------------------------- /api/posts/:id ------------------

const router = require("express").Router()
const Comment = require("../models/Comment")

router.post("/comment", async (req, res) => {
     const newComment = new Comment(req.body);
    
     try{
         const savedComment = await newComment.save();
         res.status(200).json(savedComment);
     } catch(err) {
         res.status(500).json(err);
     }
});

NOTE: I personally like to put that comment on the top of all my route files so I know what the path looks like by the time it reaches the code in this file.

GabrielMC
  • 288
  • 2
  • 7
  • Thank you for trying to help. If I follow this path, how do I assign comment to individual post? Because the comments are made under specific posts. – kinhs Sep 07 '21 at 15:23
  • You have to create the router with `.Router({ mergeParams: true });` to get the `id` of the route's mount point included in your `req.params` See https://stackoverflow.com/a/32140649/1563833 – Wyck Sep 07 '21 at 16:12
0

Because you mounted your router at /api/posts/:id, then you should change:

router.post("/posts/:id/comment", async (req, res) =>{

to:

router.post("/comment", async (req, res) =>{

And change:

const router = require("express").Router()

to:

const router = require("express").Router({ mergeParams: true })

Then your id is available at req.params.id in the handler for /comment. e.g.:

router.post("/comment", async (req, res) => {
  console.log(`Commenting on ${req.params.id)}`);
  // ...
Wyck
  • 10,311
  • 6
  • 39
  • 60
  • thank you very much for trying to help me out. What if my comment route path is like this: router.post("/post/:id/comment", async (req, res) =>{}. How do I properly mount my router without using the mergeParams? Will my api path look like this: app.use("/api/posts/:id/comment"? – kinhs Sep 07 '21 at 17:01
  • You can mount your router at `/api`. e.g.: `app.use("/api", commentRoute)` But beware `post` and `posts` are different. (maybe it was just a typo in your comment). – Wyck Sep 07 '21 at 17:11
  • I actually wanted to say router.post("/posts/:id/comment", async (req, res) =>{}). That means, I meant posts. With this comment route path, I can use app.use("/api", commentRoute) without using the mergeParams ?. – kinhs Sep 07 '21 at 17:16
  • @kinhs, That correct. You only have to use `mergeParams` if you have a nested route and the parameter comes from the parent (as in my post) In your case, if you just want the parent mount point to be a parameterless `/api` then the nested _comment_ route determines the `:id` param so the `id` parameter will be available without `mergeParams`. – Wyck Sep 07 '21 at 17:26
  • which is best, I am still a leaner. Your method seems to work because I can see my comments in the database. But if I fetch that same post, the comment will be an empty array. but the id will be there. Also, if I make comment via my postman, it returns empty body but with 200 status. And if u check the database Comment collection, you will see the same comment made. Could there be something wrong with my create comment logic? – kinhs Sep 07 '21 at 17:43
  • You have bigger fish to fry there, might even be best to start a new question now that you have your routing figured out because now it's a mongo-specific question. You have a fundamental problem that the schema for your comment doesn't include an identifier for the particular id of the post, (if comments are in a different document, much like SQL) or if they are in the same collection (like NOSQL). But you'll minimally have to refer to (as in SQL schema) or find (as in NOSQL) the post record/document (by its `id` (or by nesting) in order to add a comment. Ask a mongo expert in a new question. – Wyck Sep 07 '21 at 17:58
  • Your approached helped me in solving my problem. I am currently using the "/api" path and I have written the logic properly to push my comments into the post. Thank you. – kinhs Sep 07 '21 at 18:59