为什么Mongoose不会在更新时验证?

Cam*_*ilo 48 mongoose

我有这个代码

var ClientSchema = new Schema({
  name: {type: String, required: true, trim: true}
});

var Client = mongoose.mode('Client', ClientSchema);
Run Code Online (Sandbox Code Playgroud)

使用express,我使用此代码创建一个新客户端

var client = new Client(req.body);
client.save(function(err, data) {
  ....
});
Run Code Online (Sandbox Code Playgroud)

如果我在表单上留下名称字段为空,则mongoose不允许创建客户端,因为我在架构上按需要设置它.另外,如果我在名称前后留下空格,mongoose会在保存前删除该空格.

现在,我尝试使用此代码更新客户端

var id = req.params.id;
var client = req.body;
Client.update({_id: id}, client, function(err) {
  ....
});
Run Code Online (Sandbox Code Playgroud)

它允许我更改名称,但如果我在表单上将其留空,则mongoose不会验证并保存一个空名称.如果我在名称前后添加空格,则使用空格保存名称.

为什么mongoose在保存时验证但在更新时没有验证?我是以错误的方式做到的?

mongodb:2.4.0 mongoose:3.6.0 express:3.1.0 node:0.10.1

vic*_*ohl 73

猫鼬4.0你可以运行验证器update(),并findOneAndUpdate()使用新的标志runValidators: true.

Mongoose 4.0引入了一个运行验证器update()findOneAndUpdate()调用的选项.打开此选项将运行你的所有字段校验update()呼叫尝试$set$unset.

例如,给定OP的Schema:

var ClientSchema = new Schema({
  name: {type: String, required: true, trim: true}
});

var Client = mongoose.model('Client', ClientSchema);
Run Code Online (Sandbox Code Playgroud)

在每次更新时传递旗帜

你可以使用这样的新标志:

var id = req.params.id;
var client = req.body;
Client.update({_id: id}, client, { runValidators: true }, function(err) {
  ....
});
Run Code Online (Sandbox Code Playgroud)

pre钩子上使用标志

如果您不想每次更新时都设置标志,可以设置一个pre钩子findOneAndUpdate():

// Pre hook for `findOneAndUpdate`
ClientSchema.pre('findOneAndUpdate', function(next) {
  this.options.runValidators = true;
  next();
});
Run Code Online (Sandbox Code Playgroud)

然后你可以update()使用验证器,而不是runValidators每次都传递标志.

  • 这应该是标记为正确的答案 (7认同)
  • 在更新调用上指定`{runValidators:true}`效果很好.但**挂钩选项集对我来说在Mongoose 4.1.0中不起作用 (2认同)

Joh*_*yHK 56

你没有做错任何事情,validation在Mongoose中实现为内部中间件,而中间件在执行期间不会被执行,update因为它基本上是对本机驱动程序的传递.

如果您希望验证客户端更新,则需要find更新对象,将新属性值应用于它(请参阅下划线的extend方法),然后调用save它.

Mongoose 4.0更新

正如评论和victorkohl的回答中所述,当您在调用中包含选项时,Mongoose现在支持验证字段$set$unset运算符.runValidators: trueupdate

  • 在更新时有一些关于Mongoose验证的GitHub票证,请参见[问题860](https://github.com/LearnBoost/mongoose/issues/860),[问题892](https://github.com/LearnBoost/mongoose/issues/892)以及[问题4722](https://github.com/LearnBoost/mongoose/issues/4722).我希望他们能尽快解决这个问题. (3认同)
  • 从v3.9.3开始,update()需要另外两个选项:setDefaultsOnInsert和runValidators @see https://github.com/LearnBoost/mongoose/commit/1d8c3e96c7b11497d3325e9cf1f7ae66c9ee560e (2认同)

Moh*_*nji 11

默认情况下,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);
});
Run Code Online (Sandbox Code Playgroud)

因此,任何内置或自定义验证也将在任何更新上运行