当您定义新的猫鼬模式时,有没有办法使用"不可修改"设置(例如类型、必需等(设置字段?这意味着一旦创建新文档,就无法更改此字段。
例如,像这样:
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
该插件将拒绝对字段的每次修改尝试,它适用于
- 更新
- 更新一
- 查找一个和更新
- 更新许多
- 重新保存
它支持数组、嵌套对象等字段类型,并保护深度不变性。
插件还处理更新选项,如$set、$inc等。
您只能使用 Mongoose 进行操作,userSchema.pre
save
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);