防止使用猫鼬模式修改字段



当您定义新的猫鼬模式时,有没有办法使用"不可修改"设置(例如类型、必需等(设置字段?这意味着一旦创建新文档,就无法更改此字段。

例如,像这样:

var userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unmodifiable: true
}
})

从 Mongoose 的 5.6.0 版本开始,我们可以在模式中使用immutable: true(与前面提到的mongoose-immutable包答案完全相同(。 典型的用例是时间戳,但在您的情况下,username它是这样的:

const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
immutable: true
}
});

如果您尝试更新该字段,猫鼬将忽略修改。


比OP的要求更进一步,现在使用Mongoose 5.7.0,我们可以有条件地设置immutable属性。

const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
immutable: doc => doc.role !== 'ADMIN'
},
role: {
type: String,
default: 'USER',
enum: ['USER', 'MODERATOR', 'ADMIN'],
immutable: true
}
});

来源:Mongoose 5.6.0 中的新增功能:不可变属性和 Mongoose 5.7 中的新功能:条件不可变性,更快的文档数组。

请注意,文档明确指出,当使用标识符/名称中带有更新的函数时,不会触发"pre"中间件:

尽管在使用 update 时将值强制转换为其适当的类型,但不应用以下内容:
- 默认值
- 资源库
- 验证程序
- 中间件

如果需要这些功能,请使用首先检索文档的传统方法。

Model.findOne({ name: 'borne' }, function (err, doc) { if (err) .. doc.name = 'jason bourne'; doc.save(callback); })

因此,要么通过mongooseAPI采用上述方式,它可以触发中间件(如desoares答案中的"pre"(,也可以触发您自己的验证器,例如:

const theOneAndOnlyName = 'Master Splinter';
const UserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
default: theOneAndOnlyName
validate: {
validator: value => {
if(value != theOneAndOnlyName) {
return Promise.reject('{{PATH}} do not specify this field, it will be set automatically');
// message can be checked at error.errors['username'].reason
}
return true;
},
message: '{{PATH}} do not specify this field, it will be set automatically'
}
}
});

或者总是调用任何更新函数(例如'findByIdAndUpdate'和friends(,并以{ runValidators: true }的形式使用额外的"选项"参数,例如:

const splinter = new User({ username: undefined });
User.findByIdAndUpdate(splinter._id, { username: 'Shredder' }, { runValidators: true })
.then(() => User.findById(splinter._id))
.then(user => {
assert(user.username === 'Shredder');
done();
})
.catch(error => console.log(error.errors['username'].reason));

您也可以以非标准方式使用验证器函数,即:

...
validator: function(value) {
if(value != theOneAndOnlyName) {
this.username = theOneAndOnlyName;
}
return true;
}
...

这不会抛出"验证错误",而是悄悄地覆盖指定的值。它仍然只在使用具有指定验证选项参数的save()或更新函数时这样做。

我在字段修改方面遇到了同样的问题。

试试 https://www.npmjs.com/package/mongoose-immutable-plugin

该插件将拒绝对字段的每次修改尝试,它适用于

  1. 更新
  2. 更新一
  3. 查找一个和更新
  4. 更新许多
  5. 重新保存

它支持数组、嵌套对象等字段类型,并保护深度不变性。

插件还处理更新选项,如$set、$inc等。

您只能使用 Mongoose 进行操作,userSchema.presave

if (this.isModified('modified query')) {
return next(new Error('Trying to modify restricted data'));
}
return next();

您可以使用 Mongoose Immutable。这是一个小包,您可以使用以下命令安装,它允许您使用"不可变"属性。

npm install mongoose-immutable --save

然后使用它:

var userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
immutable: true
}
});
userSchema.plugin(immutablePlugin);

最新更新