gpt4 book ai didi

node.js - Mongoose 独特 :true pre-save hook calls hook before validation

转载 作者:太空宇宙 更新时间:2023-11-03 23:41:59 28 4
gpt4 key购买 nike

据我了解, Mongoose 预保存 Hook 在将文档插入集合之前但在验证发生之后触发。因此,如果一次验证失败,则不会调用预保存 Hook 。

就我而言,无论如何都会调用它们:

下面的简单代码的作用是尝试创建一个模式,其中用户在注册时通过 _id 引用其他用户。添加了预保存 Hook ,可以自动将新用户的 ID 推送到其推荐列表中。

因此用户 a 在没有推荐的情况下注册 -> 确定

用户 b 作为推荐人向 a 注册 -> 确定

用户 b2 使用与 b 相同的电子邮件注册(不行,是唯一的)并引用 a -> 应该失败,并且不应将 b2 的 ID 推送到 a.references

架构:

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
});
});
});
});

其他一切都检查完毕,抛出错误,发生失败,但无论如何都会保存所有预保存 Hook

知道如何解决这个问题或者验证 Hook 后是否有真正的预保存?

最佳答案

据我所知,如果您为referedBy路径提供异步验证函数,它将与预保存函数并行(有效)执行,而不是串行执行,这样会阻止预保存函数的执行。 -保存函数的执行。

您可以考虑将它们组合成一个函数,并且如果您想阻止更新referedBy对象的引用列表,直到之后,例如,电子邮件值的唯一约束已得到满足(这显然不会得到强制执行)直到实际的保存尝试),您可能希望将这部分逻辑保留在保存后 Hook 中。

干杯。

编辑

我已经通过多种方式研究过这个问题,现在一切似乎都相当清楚:

1) 自定义验证函数在预保存 Hook 之前执行,并且可以通过返回 false 来阻止预保存 Hook (当然还有保存本身)的执行。通过以下内容进行演示:

userSchema.pre('save', function (next) {
console.log('EXECUTING PRE-SAVE');
next();
});

userSchema.path('referredBy').validate(function (value, respond) {
console.log('EXECUTING referredBy VALIDATION')
respond(false);
}, 'doesntExit');

2) 不需要进行数据库查询来强制执行的内置验证器(例如“必需”约束)也会在预保存函数之前执行,并且可以阻止其执行。通过注释掉 b2 的电子邮件值分配而不是分配非唯一值来轻松演示:

var b2 = new User();
//b2.email = 'b';
b2.referredBy = a._id;

3) 需要进行数据库查询(例如强制唯一性)的内置验证器不会阻止预保存 Hook 执行。据推测,这是为了针对成功案例进行优化,否则必须涉及 1 个查询来检查唯一性,然后在通过唯一性验证后进行另一个查询以进行更新插入。

因此,验证(自定义或内置)确实在执行预保存 Hook 之前发生,除非内置验证需要执行数据库查询.

关于node.js - Mongoose 独特 :true pre-save hook calls hook before validation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21923043/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com