Почему Mongoose не проверяет на обновление?
У меня есть этот код
var ClientSchema = new Schema({
name: {type: String, required: true, trim: true}
});
var Client = mongoose.mode('Client', ClientSchema);
Используя express, я создаю новый клиент с этим кодом
var client = new Client(req.body);
client.save(function(err, data) {
....
});
Если я оставляю поле имени пустым в форме, mongoose не разрешает создавать клиент, потому что я устанавливаю его в соответствии с требованиями схемы. Кроме того, если я оставляю пробелы до и после имени, mongoose удаляет эти пробелы перед сохранением.
Теперь я пытаюсь обновить клиент с помощью этого кода
var id = req.params.id;
var client = req.body;
Client.update({_id: id}, client, function(err) {
....
});
Это позволило мне изменить имя, но если я оставлю его пустым в форме, mongoose не проверяет и не сохраняет пустое имя. Если я добавляю пустые пробелы до и после имени, он сохраняет имя с пробелами.
Почему mongoose проверяется при сохранении, но не при обновлении? Я делаю это не так?
mongodb: 2.4.0
мангуста: 3.6.0
экспресс: 3.1.0
node: 0.10.1
Ответы
Ответ 1
Вы не делаете ничего плохого, validation
реализуется как внутреннее промежуточное ПО внутри Mongoose, а промежуточное программное обеспечение не выполняется во время update
как это в основном переход к собственному драйверу.
Если вы хотите, чтобы ваше обновление клиента было проверено, вам нужно find
обновить объект, применить к нему новые значения свойств (см. underscore extend
), а затем наберите save
на нем.
Обновление Mongoose 4.0
Как отмечено в комментариях и ответах victorkohl, Mongoose теперь поддерживает проверку полей операторов $set
и $unset
, когда вы включаете опцию runValidators: true
в вызов update
.
Ответ 2
Начиная с Mongoose 4.0 вы можете запускать валидаторы на update()
и findOneAndUpdate()
с помощью нового флага runValidators: true
.
Mongoose 4.0 вводит опцию запуска валидаторов на update()
и findOneAndUpdate()
. При включении этой опции будут запущены валидаторы для всех полей, которые ваш вызов update()
пытается выполнить $set
или $unset
.
Например, данная схема OP:
var ClientSchema = new Schema({
name: {type: String, required: true, trim: true}
});
var Client = mongoose.model('Client', ClientSchema);
Передача флага при каждом обновлении
Вы можете использовать новый флаг следующим образом:
var id = req.params.id;
var client = req.body;
Client.update({_id: id}, client, { runValidators: true }, function(err) {
....
});
Использование флага на pre
hook
Если вы не хотите устанавливать флаг каждый раз, когда вы что-то обновляете, вы можете установить крюк pre
для findOneAndUpdate()
:
// Pre hook for `findOneAndUpdate`
ClientSchema.pre('findOneAndUpdate', function(next) {
this.options.runValidators = true;
next();
});
Затем вы можете update()
использовать валидаторы без передачи флажка runValidators
каждый раз.
Ответ 3
mongodb не запускает проверку при обновлении по умолчанию. чтобы проверка работала по умолчанию и при обновлении, перед подключением к mongodb вы можете установить только такие глобальные настройки:
mongoose.set('runValidators', true); // here is your global setting
mongoose.connect(config.database, { useNewUrlParser: true });
mongoose.connection.once('open', () => {
console.log('Connection has been made, start making fireworks...');
}).on('error', function (error) {
console.log('Connection error:', error);
});
и любая встроенная или пользовательская проверка будет выполняться при обновлении также
Ответ 4
В вашей модели, напр. Файл Category.js:
const CategorySchema = mongoose.Schema({
category_name : {
type : String,
required : [true, 'Category Name Is Required !'],
trim : true,
maxlength : [30, 'Category Name Is To Long !'],
unique : true,
});
const Category = module.exports = mongoose.model("Category",CategorySchema);
В вашем файле маршрута:
router.put("/",(req,res,next)=>{
Category.findOneAndUpdate(
{_id : req.body.categoryId},
{$set : {category_name : req.body.category_name} },
**{runValidators: true}**, function(err,result) {
if(err){
if(err.code === 11000){
var duplicateValue = err.message.match(/".*"/);
res.status(200).json({"defaultError":duplicateValue[0]+" Is Already Exsist !"});
}else{
res.status(200).json({"error":err.message} || {"defaultError":'Error But Not Understood !'});
}
}else{
console.log("From category.js (Route File) = "+result);
res.status(200).json({"success":"Category Updated Successfully!!"});
}
});
Ответ 5
exports.updateGroup = (request, response, next) => {
const requestObj = request.body;
var conditions = {
_id: request.body._id,
communityId: request.body.communityId
};
var newValues = {
$set: requestObj
};
Group.updateOne(conditions, newValues, { ***runValidators: true*** }, (err, group) => {
if (err) return response.json({
message: "Updation of group failed",
error: err,
status: 500
});
response.json(group);
});
};
Вам нужно добавить {runValidators: true} в качестве третьего аргумента для валидации для работы при обновлении.