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