[英]Mongoose custom validation of several fields on update
首先, 這沒有幫助。
比方說,我們有一個用戶模型:
const schema = new mongoose.Schema({
active: { type: Boolean },
avatar: { type: String }
});
const User = mongoose.model('User', schema);
當我們更新它(設置一個頭像):
// This should pass validation
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
我們希望根據當前(或更改的) active
屬性值對其進行驗證。
active
是false
active
是true
const schema = new mongoose.Schema({
active: { type: Boolean },
avatar: { type: String, validate: [validateAvatar, 'User is not active'] }
});
function validateAvatar (value) {
console.log(value); // user.avatar
console.log(this.active); // undefined
}
所以這不起作用,因為我們沒有訪問active
字段。
schema.pre('validate', function (next) {
// this will never be called
});
此掛鈎不適用於update
方法。
schema.pre('update', function (next) {
console.log(this.active); // undefined
});
這對我們不起作用,因為它無法訪問模型字段。
schema.post('update', function (next) {
console.log(this.active); // false
});
這個可行,但在驗證方面不是很好的選擇,因為只有在模型已經保存時才調用該函數。
那么有沒有一種方法可以在保存之前基於幾個字段(保存在DB和新的字段中)驗證模型,同時使用model.update()
方法?
作為總結:
{ active: false, avatar: null }
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
{ active: false, avatar: 'user1.png' }
由於使用update()
限制,我決定以這種方式解決問題:
update()
而不是
User.update({ _id: id }, { $set: { avatar: 'user1.png' } });
我用
User.findOne({ _id: id })
.then((user) => {
user.avatar = 'user1.png';
user.save();
});
在這種情況下,自定義驗證程序按預期工作。
PS我選擇這個答案對我來說是正確的,但我會給予最相關答案的賞金。
您可以使用mongoose文檔中指定的context選項執行此操作。
上下文選項
context選項允許您將更新驗證程序中的this值設置為基礎查詢。
validator
,如下所示:
function validateAvatar (value) { // When running update validators with the `context` option set to // 'query', `this` refers to the query object. return this.getUpdate().$set.active; } schema.path('avatar').validate(validateAvatar, 'User is not active');
在更新時,您需要輸入兩個選項runValidators
和context
。 所以你的更新查詢變為:
var opts = { runValidators: true, context: 'query' }; user.update({ _id: id }, { $set: { avatar: 'user1.png' }, opts });
您是否嘗試激活默認值,以便在mongodb中不會定義。
const schema = new mongoose.Schema({
active: { type: Boolean, 'default': false },
avatar: { type: String,
trim: true,
'default': '',
validate: [validateAvatar, 'User is not active']
}});
function validateAvatar (value) {
console.log(value); // user.avatar
console.log(this.active); // undefined
}
在創建時,您是否以這種方式設置用戶
var User = mongoose.model('User');
var user_1 = new User({ active: false, avatar: ''});
user_1.save(function (err) {
if (err) {
return res.status(400).send({message: 'err'});
}
res.json(user_1);
});
您可以嘗試預先“保存”鈎子。 我之前使用過它,可以在“this”中獲得值。
schema.pre('save', function (next) {
console.log(this.active);
});
希望這也和你合作!
您必須使用異步自定義驗證器 :
const schema = new mongoose.Schema({
active: { type: Boolean },
avatar: {
type : String,
validate : {
validator : validateAvatar,
message : 'User is not active'
}
}
});
function validateAvatar(v, cb) {
this.model.findOne({ _id : this.getQuery()._id }).then(user => {
if (user && ! user.active) {
return cb(false);
} else {
cb();
}
});
}
(並將runValidators
和context
選項傳遞給update()
,如Naeem的答案所示)。
但是,這將需要對每個更新進行額外查詢,這並不理想。
作為替代方案,您還可以考慮使用類似的東西(如果無法更新非活動用戶的約束比實際驗證它更重要):
user.update({ _id : id, active : true }, { ... }, ...);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.