据我所知,猫鼬预保存钩子在文档插入到集合中但在验证发生之前触发。因此,如果一个验证失败,预保存钩子将不会被调用。mongoose unique:真正的预保存钩子调用验证之前的钩子
在我的情况,他们被称为无关:
什么简单的代码波纹管的作用是试图让用户在其中通过_id注册时参考其他用户的模式。预保存挂钩被添加以自动推送新用户的ID在他们的推荐人列表中。
所以用户没有转诊登记 - >确定
用户B注册了一个推荐 - >确定
使用相同的电子邮件作为B的用户B2寄存器(也不行,是唯一的)和引用一个 - >应该失败,它不应该在a.references推B2的ID
模式:
var userSchema = new Schema({
email: {type:String, unique:true, required:true},
isVerified: {type:Boolean, default:false},
referredBy: {type:Schema.ObjectId, ref:'User'},
referred: [{type:Schema.ObjectId, ref:'User'}],
});
userSchema.pre('save', function (next) {
if (!this.isNew) return next();
if (!this.referredBy) return next();
User.findById(this.referredBy, function (err, doc) {
if (err) return next(err);
if (!doc) return next(new DbError(['referredBy not found: %s', this.referredBy]));
doc.referred.push(this._id);
doc.save(next);
}.bind(this));
});
userSchema.path('referredBy').validate(function (value, respond) {
User.findById(value, function (err, user) {
if (err) throw err;
if (!user) return respond(false);
respond(true);
});
}, 'doesntExit');
var User = mongoose.model('User', userSchema);
测试代码:
var a = new User();
a.email = 'a';
a.save(function() {
var b = new User();
b.email = 'b';
b.referredBy = a._id;
b.save(function() {
var b2 = new User();
b2.email = 'b';
b2.referredBy = a._id;
b2.save(function (err, doc) {
console.log('error:', err); // duplicate error is thrown, which is OK
console.log(!!doc); // this is false, which is OK
User.findById(a._id, function (err, result) {
console.log('# of referrals: ', result.referred.length); // 2, which is BAD
});
});
});
});
其他一切检查出来的错误抛出,失败发生,但不顾一切的预存钩保存
任何想法如何解决这一问题或验证后,如果有一个真正的预存钩?
是的,我想到了,但我试图避免结合验证,并希望有一种方法,使其如广告 – Stefan
做了一点挖掘。似乎它主要按照您期望的方式工作,除了内置唯一性验证程序的情况。有关详细信息,请参阅我的更新回答 – prattsj