根据猫鼬内置的验证器文档,我可以使用条件必填字段:
const schema = mongoose.Schema({
a: {
type: String,
required: function () {
return this.b === 1
}
},
b: {
type: Number,
required: true
}
});
在此方案中,a
仅当propertyb
等于时才需要该属性1
。
尝试创建新文档的工作符合预期:
Model.create({ b: 1 }); // throws ValidationError (property a is required)
和
Model.create({ b: 2 }); // creates document
我的问题是尝试更新现有文档并将属性设置b
为1
因此a
需要属性。
运行以下代码:
Model.findByIdAndUpdate(model._id, { b: 1 }, { new: true, runValidators: true});
意外地更新文档,而不会引发a
需要该属性的错误。
我的猜测是,验证仅针对更新的属性(property b
)运行,而不是针对整个文档。
我不确定这是预期的行为还是错误...
我想念什么吗?有什么方法可以运行整个文档的验证程序,而不仅是更新后的属性,而不必之前手动获取文档?
在尝试了中间件和验证器之后,没有任何成功,我可以通过使用transactions
(从MongoDB 4.0
和提供Mongoose 5.2.0
)来实现此要求。
// Create a transaction session
const session = await mongoose.startSession();
session.startTransaction();
// Fetch the model (pass the session)
const model = await Model.findById(modelId).session(session);
// ... update your model here
// Validate the schema
if (model.b === 1 && !model.a) {
throw new mongoose.ValidationError('property a is required');
}
// Save the changes
await model.save();
await session.commitTransaction();
请注意,我没有将附加session
到save
函数,因为使用find
以下命令获取模型已将其附加:
如果您使用会话从findOne()或find()获得Mongoose文档,则该文档将保留对该会话的引用,并将该会话用于save()。
我发现这种方法的一个问题是MongoDB
当前仅支持transactions
副本集。有一个选项可以在不使用副本集的情况下在本地运行,以供使用run-rs
要在macOS,Linux或Windows上运行本地副本集以进行开发,请使用npm全局安装run-rs并运行run-rs --version 4.0.0。Run-rs将为您下载MongoDB 4.0.0。
有关更多信息,您可以查看有关交易的Mongoose文档和MongoDB文档。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句