Node.js / mongoDB / Blog / Update Posts

Hi there,

I am writing a little blog just for the purpose of learing some backend programming. So far I am able to create, read and delete posts from my mongoDB (mLab). But I am not able to update the displayed posts. I read every tutorial so far that I could find on how to update mongoDB but none seem to work with my setup.

My model:

var blogSchema = mongoose.Schema({
  title: String,
  post: String,
  author: String,
  createdAt: {
    type: Date,
    default: new Date()
  }
});

var Blog = mongoose.model("Blog", blogSchema);

My current code for updating my posts look like this:

app.get("/editPost/:id", (req, res) => {
  let id = ObjectID(req.params.id);

  Blog.find(id, (err, post) => {
    res.render("editPost", { post: post });
  });
});

app.put("/editPost/:id", (req, res) => {
  let id = req.params.id;

  const updates = {
    title: req.body.title,
    author: req.body.author,
    post: req.body.post
  };

  Blog.update(id, updates, (err, result) => {
    if (err) {
      res.send("error occurred");
    } else {
      res.send(updates);
    }
  })

    .exec()
    .then(result => {
      res.redirect("/");
    });
});

And the html for rendering:

<form action="/editPost/:id" method="GET">
        <div class="container">
          <div class="row">
              <div class="col-sm">
            <label style="display: block;" for="title">Title: </label>
            <textarea style="padding-right: 60%" name="title"><%=post[0].title %></textarea>
          </div>
          </div>
          <br />
          <div class="row">
              <div class="col-sm">
            <label style="display: block;" for="author">Author: </label>
            <textarea style="padding-right: 60%"   name="author" ><%=post[0].author %> </textarea>
            </div>
          </div>
          <br />
          <div class="row">
              <div class="col-sm">
            <label style="display: block;" for="post">Post: </label>
            <textarea style="padding-right: 60%; resize: both; overflow: auto " name="post"><%=post[0].post %></textarea>
            </div>
          </div>
          <br />
          <button type="submit">Edit Post</button>
        </div>
      </form>

Has anyone an idea how to display and update posts in my setup?

It’s been a while since I used mongoose (and even longer since I used it with callbacks), but I guess you should either:

  1. first retrieve the blogpost, update it and then use .save()
  2. or you should use .findOneAndUpdate()

Thank you very much for your thoughts. I tried it with your methods but unfortunatelty with the same result.

I probably have the wrong design pattern in the way I display / want to update the data.

I also get the follwoing error message:

Error: Argument passed in must be a single String of 12 bytes or a string of 24 hex characters at new ObjectID 

Considering you have the mongoose id of the object you want to update already I’d be inclined to use findByIdAndUpdate and I wouldn’t mix callbacks with promises, but rather stick with one, so if using callbacks for example you’d do something like

 Blog.findByIdAndUpdate(id, updates, { new: true}, (err, result) => {
          if(err) res.send("error occurred")
          res.send(result)
})

And if using promises, note here that exec() is not really necessary but since mongoose promises are not really ‘promises’ but rather thenables , adding exec() ensures it is a bonafide JS promise,

Blog.findByIdAndUpdate(id, updates, { new: true})
   .exec()
   .then(result => res.redirect("/"))
   .catch(err => res.send('Error'))

thank you for your input. I am able to update my posts now but only with POST request, not PUT request.

The next problem is that there is an empty req.params.id within my POST request and therefore my updates happen to posts that were not intended to.

  1. I believe HTML forms only support GET or POST methods only, which your form is using
    <form action="/editPost/:id" method="GET">
    Try sending your update with a third party (like axios) or native fetch, with PUT as a send option and express should handle the request.
  2. Can’t really say without looking closer at your code, sounds like the route parameter you are sending is malformed or incorrect, do a console.log (req.params.id) first thing in the handler of your post request and see what is hitting the server first.

Forms only support GET and POST, but there is an npm package method-override that could help with that.

1 Like