Mongoose findByIdAndUpdate not updating the document

Issue

Been trying to use Mongoose findByIdAndUpdate to update the document by ID, the operation runs without error but change is not reflected on database.

on server log i can only see users.findOne logged when I run the API, shouldn’t mongoose run update along with it aswell. I can get/create/delete user without any issue.

interface

export interface User {
  _id: string;
  email: string;
  password: string;
}

model

const userSchema: Schema = new Schema({
  email: {
    type: String,
    required: true,
    unique: true,
  },
  password: {
    type: String,
    required: true,
  },
});

controller

public updateUser = async (req: Request, res: Response, next: NextFunction) => {
    try {
      const userId: string = req.params.id;
      const userData: CreateUserDto = req.body;
      const updateUserData: User = await this.userService.updateUser(userId, userData);

      res.status(200).json({ data: updateUserData, message: 'updated' });
    } catch (error) {
      next(error);
    }
  };

service

  public async updateUser(userId: string, userData: CreateUserDto): Promise<User> {
    if (isEmpty(userData)) throw new HttpException(400, "You're not userData");

    if (userData.email) {
      const findUser: User = await this.users.findOne({ email: userData.email });
      if (findUser && findUser._id != userId) throw new HttpException(409, `You're email ${userData.email} already exists`);
    }

    if (userData.password) {
      const hashedPassword = await bcrypt.hash(userData.password, 10);
      userData = { ...userData, password: hashedPassword };
    }

    const updateUserById: User = await this.users.findOneAndUpdate({ _id: userId }, { userData }, { new: true });
    if (!updateUserById) throw new HttpException(409, "You're not user");

    return updateUserById;
  }

dtos

import { IsEmail, IsString } from 'class-validator';

export class CreateUserDto {
  @IsEmail()
  public email: string;

  @IsString()
  public password: string;
}

Log when I run the update API

mongodbexpress | {"t":{"$date":"2021-08-23T05:19:26.698+00:00"},"s":"I",  "c":"STORAGE",  "id":22430,   "ctx":"Checkpointer","msg":"WiredTiger message","attr":{"message":"[1629695966:698802][1:0x7f5f10065700], WT_SESSION.checkpoint: [WT_VERB_CHECKPOINT_PROGRESS] saving checkpoint snapshot min: 664, snapshot max: 664 snapshot count: 0, oldest timestamp: (0, 0) , meta checkpoint timestamp: (0, 0) base write gen: 2092"}}
server    | Mongoose: users.findOne({ email: '[email protected]' }, { projection: {} })
server    | Mongoose: users.findOne({ _id: ObjectId("6122ae51d922ae0a85b85484") }, { new: true, projection: {} })
server    | 2021-08-23 05:19:27 info: PUT /users/6122ae51d922ae0a85b85484 200 75.025 ms - 

Solution

The update doesn’t work because you are passing { userData } as update parameter to findOneAndUpdate(). That equivalent to { userData: userData } and not fit with your schema. To solve it, you just need to make a little change:

const updateUserById: User = await this.users.findOneAndUpdate({ _id: userId }, userData, { new: true });

Answered By – Cuong Le Ngoc

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published