Mongoose .pre('save') 不会触发
Posted
技术标签:
【中文标题】Mongoose .pre(\'save\') 不会触发【英文标题】:Mongoose .pre('save') does not triggerMongoose .pre('save') 不会触发 【发布时间】:2015-07-20 09:53:37 【问题描述】:我有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')
有一个额外的模式来存储递增唯一索引 Quote.number
我试图建立的递增数字。在每次保存之前,都会调用quotesSchema.pre('save')
来读取、增加nextQuoteNumber
并将其作为this.number
分别传递给next()
函数。
但是,当在别处保存 Quote
时,整个 .pre('save')
函数似乎不会触发。 Mongoose 中止保存,因为 number
是必需的,但未定义,并且没有 console.log()
我写入函数输出任何内容。
【问题讨论】:
【参考方案1】:使用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();
);
);
【讨论】:
谢谢。每当实际保存时,我最终只是在我的pre('save')
中执行该操作,因为它最终不会经常发生。我认为如果我不在我的number
上设置required: true
,我的变体也会起作用吗?
非常感谢!我有一个未初始化的 required
unique
字段,并且尝试预保存挂钩不起作用,直到我像你说的那样切换到验证。【参考方案2】:
我遇到了 pre('validate') 没有帮助的情况,因此我使用了 pre('save')。我读到有些操作是直接在数据库上执行的,因此不会调用 mongoose 中间件。我更改了我的路由端点,它将触发 .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();
);
【讨论】:
【参考方案3】:在某些情况下我们可以使用
UserSchema.pre<User>(/^(updateOne|save|findOneAndUpdate)/, function (next)
但我在函数内部使用“this”来获取数据,并且不适用于 findOneAndUpdate 触发器
我需要使用
async update (id: string, doc: Partial<UserProps>): Promise<User | null>
const result = await this.userModel.findById(id)
Object.assign(result, doc)
await result?.save()
return result
代替
async update (id: string, doc: Partial<UserProps>): Promise<User | null>
const result = await this.userModel.findByIdAndUpdate(id, doc, new: true, useFindAndModify: false )
return result
【讨论】:
【参考方案4】:对于被 Google 重定向到这里的人,请确保您在 methods
和挂钩声明之后调用 mongoose.model()
。
【讨论】:
以上是关于Mongoose .pre('save') 不会触发的主要内容,如果未能解决你的问题,请参考以下文章
Mongoose 是不是提供对 pre('save') 中属性先前值的访问?
Mongoose pre.save() 异步中间件未按预期工作
Mongoose pre.save() 异步中间件未按预期工作