Reputation: 99
i have an express app with a put
request that updates a phonebook if i found that the person's name already exists in this phone book (i'm using the "mongoose-unique-validator" that have the unique: true
option in validation)
but i have the problem with this put
request only when i set findByIdAndUpdate
's runValidators
to true
here is my code
the schema
const personSchema = new mongoose.Schema({
name: { type: String, required: true, minlength: 3, unique: true },
number: {
type: String,
required: true,
validate: {
validator: function (str) {
//the function to validate the number
},
message: "phone number must contain at least 8 digits",
},
},
});
personSchema.plugin(uniqueValidator);
personSchema.set("toJSON", {
transform: (document, returnedObject) => {
returnedObject.id = returnedObject._id.toString();
delete returnedObject._id;
delete returnedObject.__v;
},
});
const Person = mongoose.model("Person", personSchema);
the put request
app.put("/api/persons/:id", (req, res, next) => {
const id = req.params.id;
console.log(id);
const body = req.body;
const person = {
name: body.name,
number: body.number,
};
// opts is supposed to be true; and this is where i have the problem
const opts = { runValidators: false };
Person.findByIdAndUpdate(id, person, opts)
.then((updatedPerson) => {
res.json(updatedPerson);
})
.catch((error) => next(error));
});
the error handler
const errorHandler = (error, req, res, next) => {
console.error(error.message);
if (error.name === "CastError" && error.kind == "ObjectId") {
return res.status(400).send({ error: "malformatted id" });
} else if (error.name === "ValidationError") {
return res.status(400).json({ error: error.message });
}
next(error);
};
app.use(errorHandler);
the error i'm getting is
error: "Validation failed: name: Cannot read property 'ownerDocument' of null"
Upvotes: 1
Views: 1035
Reputation: 31
@oussama ghrib If you're not updating the name and you're only updating the number (as you indicated), the update object can just have the phone number, like below:
app.put('/api/persons/:id', (req, res, next) => {
const { number } = req.body
Person.findByIdAndUpdate(req.params.id, { number }, {
new: true,
runValidators: true,
context: 'query'
})
.then((updatedPeep) => {
res.json(updatedPeep)
})
.catch((err) => next(err))
})
If you're using runValidators: true
you also need context: 'query'
as explained here: https://github.com/blakehaswell/mongoose-unique-validator#find--updates
findOneAndUpdate
works like findByIdAndUpdate
for this purpose.
Upvotes: 3
Reputation: 18
The issue is with your usage of: findByIdAndUpdate(id, update, opts)
The update object should be properties you want to update otherwise it will also to try update the id.
Solution:
app.put("/api/persons/:id", (req, res, next) => {
const { name, number } = req.body;
Person.findByIdAndUpdate(req.params.id, { name, number }, opts )
.then((updatedPerson) => {
res.json(updatedPerson);
})
.catch((err) => next(err));
}
https://mongoosejs.com/docs/api/model.html#model_Model.findByIdAndUpdate
Upvotes: 0