我想在mongoose中调用更新时生成一个slug,现在我有了这个并且它可以工作。
schema.pre('update', function (next) {
const title = this._update.$set['title']
this._update.$set['slug'] = slugify(title.toLowerCase())
next()
})
问题是 slug 是 unique:true 字段,所以如果添加两个标题相同的帖子,我会收到错误,例如:
"slug: post-2\" already exists."
所以现在在调用 next()之前我想确定我的slug是否已经存在调用find,现在我有了这个代码:
.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
我该如何继续?
答案 0 :(得分:0)
尝试这样的事情
// 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'));
});
})
答案 1 :(得分:0)
这是我的解决方案,如果没有必要,可以避免更换slu
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)
})
})
答案 2 :(得分:0)
如果没有使用async / await进行回调,代码看起来会更好:
schema.pre('update', async function() {
//...
let doc = await this.model.findOne({/* some filter */});
//...
this.update({}, { $set:{ slug } });
});
还应考虑没有_id,否则更新会影响多个文档。
也可以使用upsert
选项创建新文档。
我建议使用一些existing solution:
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 }
});