Javascript 在mongoose schema.pre上生成唯一的slug。(';更新';)

Javascript 在mongoose schema.pre上生成唯一的slug。(';更新';),javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,我想在mongoose中调用update时生成一个slug,现在我有了它,它可以工作了 schema.pre('update', function (next) { const title = this._update.$set['title'] this._update.$set['slug'] = slugify(title.toLowerCase()) next() }) 问题是slug是一个唯一的:true字段,因此如果添加两篇标题相同的文章,我会得到一个错误,

我想在mongoose中调用update时生成一个slug,现在我有了它,它可以工作了

schema.pre('update', function (next) {
    const title = this._update.$set['title']
    this._update.$set['slug'] = slugify(title.toLowerCase())
    next()
})
问题是slug是一个唯一的:true字段,因此如果添加两篇标题相同的文章,我会得到一个错误,例如:

"slug: post-2\" already exists."
因此,在调用next()之前,我想确定调用find的slug是否已经存在,现在我有以下代码:

.pre('update', function (next) {
    const title = this._update.$set['title']
    this._update.$set['slug'] = slugify(title.toLowerCase())

    this._find({ slug }, function (err, docs) {
        if (err)
            console.log(err)
        else
            console.log(docs)
        next()
    })
})
但是当调用时,我得到以下错误:

          ? callback(null, docs)
            ^

TypeError: callback is not a function

我该如何继续?

试试这样的方法

// uniq slug generator function, converts `text` to `text1` if `text` exists 
schema.statics.generateSlug = function(text, suffix, callback){
    var _this = this;
    var possibleText = text + (suffix || '');
    _this.findOne({
        slug: slugify(possibleText.toLowerCase())
    }, function(err, item){
        if(!err) {
            if(!item) {
                callback(possibleText);
            } else {
                return _this.generateSlug(text, (suffix || 0) + 1, callback);
            }
        } else {
            callback(null);
        }
    });
};

schema.pre('update', function (next) {
    var _this = this;
    const title = _this._update.$set['title'];
    _this.generateSlug(title, null, function(possibleSlug) {
        if (possibleSlug) {
             _this._update.$set['slug'] = possibleSlug;
             next();
        } else return next(new Error('No possible slug'));

    });
})

这是我的解决方案,以避免在不必要时更改slug

Post.statics.slugify = function (next) {
    const title = this._update.$set['title']
    const _id = this._conditions['_id']

    const that = this
    this.model.slugify(title, _id, null, slug => {
        that._update.$set['slug'] = slug
        next()
    })
}

Post.pre('validate', function (text, _id, suffix, cb) {
    const field = text + (suffix || '')
    const slug = Slugify(field.toLowerCase())

    const that = this
    that.findOne({ slug }, (err, item) => {
        if (!err) {
            if (item)
                // Checks if current document has already the currect slug
                if (`${ item._id }` === `${ _id }`)
                    cb(slug)
                else
                    return that.slugify(`${ text }`, _id, (suffix || 0) + 1, cb)
            else
                cb(slug)
        }
        else
            cb(null)
    })
})

如果不使用异步/等待回调,代码看起来会更好:

schema.pre('update', async function() {
    //...
    let doc = await this.model.findOne({/* some filter */});
    //...
    this.update({}, { $set:{ slug } });
});

也考虑不存在ID ID或更新会影响乘法文档。 还可以使用

upsert
选项创建新文档

我建议使用一些:


这是可行的,但是使用这个解决方案,每次你更新同一篇文章并且标题相同时,都会添加到slug\u 1中,即使没有其他文章具有相同的slug。在添加后缀之前,它必须检查找到的slug是否来自其他帖子,如何实现这一点?好的,这是我的解决方案,以避免在不必要时更改slug。[我试图删除此注释,但无法删除,我将在其他注释中发布代码]
var mongoose = require('mongoose'),
    slug = require('mongoose-slug-updater'),
    mongoose.plugin(slug),
    Schema = mongoose.Schema,
    schema = new Schema({
        title: String,
        slug: { type: String, slug: "title", unique: true }
});