Node.js 使用mongoose钩子在出现重复密钥错误时重试保存
我想使用mongoose中间件钩子重新尝试保存文档,以防初始保存失败并出现重复密钥错误。用例如下所示: 我的模型使用自动生成的slug进行识别。例如,Node.js 使用mongoose钩子在出现重复密钥错误时重试保存,node.js,mongodb,mongoose,mongoose-plugins,Node.js,Mongodb,Mongoose,Mongoose Plugins,我想使用mongoose中间件钩子重新尝试保存文档,以防初始保存失败并出现重复密钥错误。用例如下所示: 我的模型使用自动生成的slug进行识别。例如,项目,项目2,项目3,…,项目n。如果项已经存在,则应向slug添加计数器。我不能提前检查“下一个”slug,因为我需要在任何情况下避免冲突 由于这种逻辑将涉及到几个不同的模型,我想将其隔离到一个mongoose插件中 这个想法可能吗?例如,schema.post('save',handler)仅在成功保存时执行。还有其他钩子可以利用吗?我正在使用
项目
,项目2
,项目3
,…,项目n
。如果项
已经存在,则应向slug添加计数器。我不能提前检查“下一个”slug,因为我需要在任何情况下避免冲突
由于这种逻辑将涉及到几个不同的模型,我想将其隔离到一个mongoose插件中
这个想法可能吗?例如,
schema.post('save',handler)
仅在成功保存时执行。还有其他钩子可以利用吗?我正在使用pre-save钩子检查slug是否已经存在,并使用下面的代码,到目前为止,它似乎工作正常
pageSchema.pre('save', function(next){
var page = this;
page.createdDT = new Date();
page.updatedDT = new Date();
page.slug = page.title.slug(); // create slug from title
var re = new RegExp(page.slug, 'i');
mongoose.models["page"].find({slug: { $regex: re}}, function(err, pages){
// slug doesn't exist, good to go
if(!err && !pages) return next();
var slugs = [];
// let's get all slugs
pages.forEach(function(page){
slugs.push(page.slug);
});
// keep increasing `i` until slug is unique
// set i to 1 to avoid hello-0
var i = 1;
var tempSlug = page.slug;
while(slugs.indexOf(tempSlug) >= 0){
tempSlug = page.slug + '-' + i;
i++;
}
//unique slug for example "hello-2"
page.slug = tempSlug;
next();
});
});
我最终采用了所使用的解决方案,并根据我们的需要进行了调整。虽然此变体不单独与前/后钩子一起工作,但它确保了原子性(即不预先检查可用的slug,然后保存,而只是重新尝试)
中心思想是覆盖模型的
save
函数(请参见enhanceModel
函数),并提供一个包装器,该包装器通过段塞冲突捕获唯一错误,然后重新尝试保存(而不是附加随机字符串,我们希望采用序列号方法)。谢谢您的建议。这个解决方案的潜在问题是,检查可用的slug和保存新文档不是原子的。老实说,目前这不是一个大问题,但我想从一开始就避免未来的陷阱。