2015-10-20 67 views
2

我一直在尝试运行自定义验证程序以检查用户输入的名称是否已存在于数据库中。因为,mongoDb将大写和小写名称视为不同,我为它创建了自己的验证器。在猫鼬更新查询中运行自定义验证

function uniqueFieldInsensitive (modelName, field){ 
return function(val, cb){ 
    if(val && val.length){ // if string not empty/null 

     var query = mongoose.models[modelName] 
      .where(field, new RegExp('^'+val+'$', 'i')); // lookup the collection for somthing that looks like this field 

     if(!this.isNew){ // if update, make sure we are not colliding with itself 
      query = query.where('_id').ne(this._id) 
     } 

     query.count(function(err,n){ 
      // false when validation fails 
      cb(n < 1) 
     }) 
    } else { // raise error of unique if empty // may be confusing, but is rightful 
     cb(false) 
    } 
} 

}

现在的问题是,验证,同时节省在DB文件运行,但不能同时更新。

因为我使用猫鼬版本4.x,我也试过在我的更新查询中使用{ runValidators: true }。这不起作用,因为我的验证器中的'this'关键字是'null',而在更新的情况下,它指的是在保存的情况下更新的文档。

能否让我知道是否有一些我错过了或有任何其他方式,我可以在更新查询中运行自定义验证器。

回答

2

最后我找到了一条出路。 根据MongoDB文档,它说:

首先,更新验证程序只检查$ set和$ unset操作。更新验证器不会检查$ push或$ inc操作。 第二个也是最重要的区别在于,在文档验证器中,这是指正在更新的文档。在更新验证器的情况下,没有底层文档,所以在您的自定义验证器中它将为空。 参见:不是我们查询更新()Validators for update()

所以,现在我们只调用save左()。既然save()调用了所有的自定义和内置的验证器,我们的验证器也会被调用。我取得了这样的:这里req.libraryStep

function(req, res, next) { 
_.assign(req.libraryStep, req.body); 

req.libraryStep.save().then(function(data){ 
    res.json(data); 
}).then(null, function (err) { 
    console.info(err); 
    var newErr = new errorHandler.error.ProcessingError(errorHandler.getErrorMessage(err)); 
    next(newErr); 
    }); 
}; 

注意的是,我从数据库中查询该文档。我使用了lodash方法assign,它接受更新的json并将其分配给现有的数据库文档。

https://lodash.com/docs#assign

我不认为这是理想的方式,但作为即日起至猫鼬犯规拿出支持自定义的验证,我们可以用它来解决我们的问题。

1

这是一个相当古老的线程,但我想更新那些像我一样遇到它的人的答案。

虽然您在更新验证程序(每个文档)中为空的this的上下文是正确的,但您可以使用context选项设置this的上下文。 See the docs

但是,插件也存在,将检查您设置的字段的唯一性:mongoose-unique-validator。我用它来检查重复的电子邮件。这也有不区分大小写的选项,所以我会检查出来。它也可以使用update命令和选项正确运行。