2015-10-20 54 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命令和選項正確運行。