Mongoose .pre(' save')不会触发

时间:2015-05-09 15:04:23

标签: node.js mongodb express mongoose

我有mongoose.model('quotes')的以下模型:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var quotesSchema = new Schema({
    created: { type: String, default: moment().format() },
    type: { type: Number, default: 0 },
    number: { type: Number, required: true },

    title: { type: String, required: true, trim: true},
    background: { type: String, required: true },

    points: { type: Number, default: 1 },
    status: { type: Number, default: 0 },
    owner: { type: String, default: "anon" }
});

var settingsSchema = new Schema({
    nextQuoteNumber: { type: Number, default: 1 }
});

// Save Setting Model earlier to use it below
mongoose.model('settings', settingsSchema);
var Setting = mongoose.model('settings');

quotesSchema.pre('save', true, function(next) {
  Setting.findByIdAndUpdate(currentSettingsId, { $inc: { nextQuoteNumber: 1 } }, function (err, settings) {
    if (err) { console.log(err) };
    this.number = settings.nextQuoteNumber - 1; // substract 1 because I need the 'current' sequence number, not the next
    next();
  });
});

mongoose.model('quotes', quotesSchema);

mongoose.model('settings')还有一个额外的Schema来存储递增的唯一索引Quote.number我想要建立的递增数字。在每次保存之前,系统会调用quotesSchema.pre('save')来读取,增加nextQuoteNumber this.number next().pre('save')函数。

但是,在其他地方保存Quote时似乎没有触发整个number函数。 Mongoose中止了保存,因为console.log()是必需的但没有定义,并且没有{{1}}我写入函数输出任何内容。

3 个答案:

答案 0 :(得分:28)

使用pre('validate')代替pre('save')来设置必填字段的值。 Mongoose在保存之前验证文档,因此如果存在验证错误,则不会调用save中间件。将中间件从save切换到validate将使您的函数在验证之前设置数字字段。

quotesSchema.pre('validate', true, function(next) {
  Setting.findByIdAndUpdate(currentSettingsId, { $inc: { nextQuoteNumber: 1 } }, function (err, settings) {
    if (err) { console.log(err) };
    this.number = settings.nextQuoteNumber - 1; // substract 1 because I need the 'current' sequence number, not the next
    next();
  });
});

答案 1 :(得分:4)

对于被 Google 重定向到此处的人,请确保您在调用 mongoose.model() AFTER methods 和 hooks 声明。

答案 2 :(得分:0)

我遇到了pre('validate')没有帮助的情况,因此我使用了pre('save')。我读到一些操作是直接在数据库上执行的,因此不会调用猫鼬中间件。我更改了路由端点,这将触发.pre('save')。我用Lodash解析了正文,仅更新了传递给服务器的字段。

router.post("/", async function(req, res, next){
    try{
        const body = req.body;
        const doc  = await MyModel.findById(body._id);
        _.forEach(body, function(value, key) {
            doc[key] = value;
        });

        doc.save().then( doc => {
            res.status(200);
            res.send(doc);
            res.end();
        });

    }catch (err) {
        res.status(500);
        res.send({error: err.message});
        res.end();
    }

});