Javascript 在mongoose schema.pre上生成唯一的slug。(';更新';)
我想在mongoose中调用update时生成一个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字段,因此如果添加两篇标题相同的文章,我会得到一个错误,
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 }
});