防止使用Mongoose架构修改字段

0h4hbjxa  于 2022-09-21  发布在  Go
关注(0)|答案(6)|浏览(226)

有没有办法用“不可修改”的设置(如类型、必填等)来设置字段?当您定义新的Mongoose架构时?这意味着,一旦创建了新文档,此字段就不能更改。

例如,如下所示:

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

nx7onnlm1#

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

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

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

现在,在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
  }
});

来源:What's New in Mongoose 5.6.0: Immutable PropertiesWhat's New in Mongoose 5.7: Conditional Immutability, Faster Document Arrays

iyzzxitl

iyzzxitl2#

请注意,文档中明确指出,在使用标识符为UPDATE/名称为UPDATE的函数时,不会触发‘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'
    }
  }
});

或者始终使用{ runValidators: true }形式的附加‘Options’参数调用任何更新函数(例如,‘findByIdAndUpdate’和Friends),例如:

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;
}
...

这不会引发“ValidationError”,而是静默重写指定的值。只有在使用带有指定验证选项参数的save()或UPDATE函数时,它才会这样做。

pw9qyyiw

pw9qyyiw3#

我在现场修改时也遇到了同样的问题。

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

该插件将拒绝对字段的每一次修改尝试,它的工作方式为

1.更新
1.更新1
1.FindOneAndUpdate
1.更新多个
1.重新保存

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

插件还处理更新选项,如$SET、$INC等。

wko9yo5t

wko9yo5t4#

您只能在userSchema.pre``save中对Mongoose执行此操作:

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

pcww981p5#

您可以使用Mongoose Immutable。这是一个可以用下面的命令安装的小程序包,它允许您使用“不可变”属性。

npm install mongoose-immutable --save

然后使用它:

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

5uzkadbs6#

像这样使用不可变变量:True

相关问题