Node.js 使用mongoose钩子在出现重复密钥错误时重试保存

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)仅在成功保存时执行。还有其他钩子可以利用吗?我正在使用

我想使用mongoose中间件钩子重新尝试保存文档,以防初始保存失败并出现重复密钥错误。用例如下所示:

我的模型使用自动生成的slug进行识别。例如,
项目
项目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和保存新文档不是原子的。老实说,目前这不是一个大问题,但我想从一开始就避免未来的陷阱。