skip to Main Content

I’m currently building out the backend of my application using Express and Mongoose. I’d like to be able to update an existing user with new details.

Currently my flow is a user uses the /signup endpoint with an email/password. Then they use the /login endpoint to get a token.

I’m able to successfully get the user with a GET to the /profile endpoint, but I’d like to be able to POST to the /profile endpoint with a JSON object, and have those values added to the user model. Here is my function.

I’ve looked at the mongoose docs and on here, and nothing seems to work for me.

I know I’m getting back the correct user, but it’s not even being updated. Even when I check the DB it’s not updated.

And the catch isn’t catching any errors.

router.post('/profile', async (req, res, next) => {
  const { _id } = req.user;
  const { firstName, lastName, role } = req.body;

  try {
    const user = await UserModel.findOneAndUpdate(
      { _id: _id },
      {
        $set: {
          firstName,
          lastName,
          role,
        },
      }
    );
    console.log(user);
  } catch (error) {
    console.error('Error updating user:', error);
    res.status(500).json({ message: 'Internal Server Error' });
  }

  res.send({});
}); 

3

Answers


  1. Chosen as BEST ANSWER

    I solved it. I'll blame the fact I'm new to this and it was late.

    But I didn't have the new fields on the UserModel, so mongoose didn't know what to with the new data.

    As soon as I added the fields in to the UserModel, my code worked first time.

    Thanks for everyones help though, it did help with the debugging.


  2. Using findByIdAndUpdate would be better because of the need to find it by the document’s ObjectId. Also, need to add {new: true} for returning the modified document:

    router.post('/profile', async (req, res, next) => {
      const { _id } = req.user;
      const { firstName, lastName, role } = req.body;
    
      try {
        const user = await UserModel.findByIdAndUpdate(
          _id,
          {
              firstName,
              lastName,
              role
          },
          { new: true }
        );
        console.log(user);
      } catch (error) {
        console.error('Error updating user:', error);
        res.status(500).json({ message: 'Internal Server Error' });
      }
    
      res.send({});
    }); 
    

    As another option, you can use then-catch instead of try-catch to make the code simpler and clearer:

    return await UserModel.findByIdAndUpdate(
          _id,
          {
              firstName,
              lastName,
              role
          },
          { new: true }
        )
        .then(user => {
             console.log(user);
             return res.send({});
        })
        .catch(error => {
             console.error('Error updating user:', error);
             return res.status(500).json({ message: 'Internal Server Error' });
        });
    

    Also, if the req.body only includes update fields, then you can use it as a short way:
    (However, creating an update model by taking properties from the request would be clearer!)

    const updatedUserModel = req.body;
    await UserModel.findByIdAndUpdate(_id, updatedUserModel, { new: true });
    

    Here is the documentation link: Mongoose – findByIdAndUpdate

    Hope, it’s clear and helpful

    Login or Signup to reply.
  3. You need to set new:true in the fincOneAndUpdate object.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search