node.js - 当MongoDB中至少需要一个子文档时,有什么更好的方法来防止删除所有子文档
问题描述
采用 mongoose 中定义的简单模式,如下所示:
const Person = new Schema({
username: {
type: String,
index: true,
},
roles: [{
type: Schema.Types.ObjectId,
ref: 'Role',
required: [true,
'Role is required'],
}],
})
当您在不提供至少一个角色的情况下保存新记录时,MongoDB 将抛出需要角色的错误。
我有另一段代码,您可以在其中更新(添加或删除)角色数组中的角色。但是,我可以使用下面的代码段删除所有角色。
Person.findOneAndUpdate({_id: 'some id'}, {
$pull: {
roles: {
$in: [...list of ids,]
}
}
}, {new: true}).populate('roles').exec()
假设我列出了该人拥有的所有角色,我将删除它们,使该人没有任何角色。
如何强制执行需要角色的早期要求?是否有一个简单的 hack 或者我应该只写一段代码来验证这个删除并自己执行它?
解决方案
您之所以能够删除所有角色,并且所需的验证不起作用,因为验证是作为 Mongoose 中的内部中间件实现的,并且在更新期间不会执行中间件。你可以在这里阅读更多关于它的信息。
如果您使用的是MongoDB 4.0 或更高版本,则可以在调用中使用runValidators: true
选项。您可以在Mongoose 更新验证器文档update
中阅读有关 runValidators 选项的更多信息。
你可以试试下面的代码(虽然我还没有测试过):
Person.findOneAndUpdate({_id: 'some id'}, {
$pull: {
roles: {
$in: [...list of ids,]
}
}
}, {new: true, runValidators: true}).populate('roles').exec()
根据官方 Mongoose 文档,更新验证器适用于以下运算符(和 MongoDB 版本):
- $set
- $未设置
- $push (>= 4.8.0)
- $addToSet (>= 4.8.0)
- $pull (>= 4.12.0)
- $pullAll (>= 4.12.0)
或者你也可以做的是设置一个Pre
钩子findOneAndUpdate
,
// Pre hook for `findOneAndUpdate`
ClientSchema.pre('findOneAndUpdate', function(next) {
this.options.runValidators = true;
next();
});
如果你有MongoDB < 4.0
然后您可以使用 找到文档,在文档中.findOne()
设置新属性,然后尝试使用 再次保存.save()
。这应该运行验证。
推荐阅读
- android-studio - 如何修复不同版本的依赖错误?
- java - 存储键=>值对的最佳方式是什么,有时可能会被删除?
- reactjs - setValue 将属性设置为未定义的反应钩子形式
- go - go run 命令不会在同一路径中拾取非 go 文件
- azure - Powershell 脚本切换参数
- javascript - 如何用纯 JS 嵌套和链接我的类函数?
- swift - 为什么将日期作为带有时区的字符串在我将其转换为日期时会变回 UTC 时间?
- mysql - (后端网络开发)Git-bash 终端和本地主机只是在连接数据库时挂起
- python - 聚合具有多对一关系的多个实例
- angular - this.formDef = 未定义