4

我想使用 mongoose 中间件挂钩重新尝试保存文档,以防初始保存因重复键错误而失败。用例如下:

我的模型使用自动生成的 slug 进行识别。例如item, item-2, item-3, ..., item-n。如果item已经存在,则应在 slug 中添加一个计数器。我无法提前检查“下一个”slug,因为我需要在任何情况下避免冲突。

由于这个逻辑会涉及到几个不同的模型,我想把它隔离成一个猫鼬插件。

这个想法可能吗?例如schema.post('save', handler),仅在成功保存时执行。还有其他可以利用的钩子吗?

4

2 回答 2

0

我正在使用 pre save hook 来检查 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();
    }); 
});
于 2015-11-25T17:27:33.833 回答
0

我最终选择了 使用的解决方案mongoose-uniqueslugs,我适应了我们的需求。虽然此变体不仅仅适用于 pre/post 钩子,但它确保了原子性(即不提前检查可用的 slug 然后保存,而只是重新尝试)。

中心思想是覆盖模型的save函数(参见enhanceModel函数)并提供一个包装器,该包装器通过 slug 碰撞捕获独特的错误,然后重新尝试保存(而不是附加的随机字符串,我们想要一个序列号方法)。

于 2015-11-26T11:20:21.790 回答