Search code examples
node.jsmongodbexpressmongoose

updateOne and findOneAndUpdate on MongoDB not working properly in Node.js


I have the following code:

exports.dashboardUpdateNote = async (req, res, next) => {
    var updateNote = {
        "title": req.body.title,
        "body": req.body.body1,
    }
    await Note.findOneAndUpdate({ _id: req.body.note_id }, { $set: updateNote })
        .then((Successful) => {
            console.log('Successful: ', Successful)
        })
    return res.redirect('/dashboard')
}

It redirected but no changes(updates) occure. Then I made this change in the code(Adding: { upsert: true }):

exports.dashboardUpdateNote = async (req, res, next) => {
    var updateNote = {
        "title": req.body.title,
        "body": req.body.body1,
    }
    await Note.findOneAndUpdate({ _id: req.body.note_id }, { $set: updateNote }, { upsert: true })
        .then((Successful) => {
            console.log('Successful: ', Successful)
        })
    return res.redirect('/dashboard')
}

It redirected and the changes(updates) occured, but when I click the (note) which I have updated to view it it gives this error:

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:399:5)
    at ServerResponse.setHeader (node:_http_outgoing:644:11)
    at ServerResponse.header (C:\Users\hp\NODE\Notes\node_modules\express\lib\response.js:794:10)     
    at ServerResponse.contentType (C:\Users\hp\NODE\Notes\node_modules\express\lib\response.js:624:15)
    at ServerResponse.send (C:\Users\hp\NODE\Notes\node_modules\express\lib\response.js:149:14)       
    at done (C:\Users\hp\NODE\Notes\node_modules\express\lib\response.js:1035:10)
    at tryHandleCache (C:\Users\hp\NODE\Notes\node_modules\ejs\lib\ejs.js:280:5)
    at exports.renderFile [as engine] (C:\Users\hp\NODE\Notes\node_modules\ejs\lib\ejs.js:491:10)     
    at View.render (C:\Users\hp\NODE\Notes\node_modules\express\lib\view.js:135:8)
    at tryRender (C:\Users\hp\NODE\Notes\node_modules\express\lib\application.js:657:10)

But when I click a note which I never updeted to view it no error occurs and the note appears. (I forgot to write that the note which must be updated didn't updated actually, it added another new note, so the notes increases one after every updating. )


Solution

  • You are mixing await and then blocks and do not have any error handling so you don't know if there was an error in saving the document. The actual error you are getting is when to try to send a response after you send a response, typically outside of a block scope you don't account for or haven't returned from.

    The findOneAndUpdate method takes an update document as the second argument so just pass the updateNote object and mongoose will update the title and body properties for you.

    A finished function might look like this:

    exports.dashboardUpdateNote = async (req, res, next) => {
       try{
          console.log(req.body); //< make sure you have parsed data in req.body
          const updateNote = {  //< use const instead of var
            title: req.body.title,
            body: req.body.body1,
          }
          const doc = await Note.findOneAndUpdate({_id: req.body.note_id}, 
             updateNote, 
             {new: true}  //< return the updated document
          );
          if(!doc){ //< doc will be null if no document was found
             return res.status(400).json({
                message: 'No document found.'
             });
          }
          // Document was updated so return to dashboard
          console.log('Successful: ', doc)
          return res.redirect('/dashboard')
       }catch(err){
          console.log(err)
          // Handle the error
          return res.status(500).json({
               message: 'Error on server.'
          });
       }
    }