【问题标题】:Prevent field modification with Mongoose Schema使用 Mongoose Schema 防止字段修改
【发布时间】:2018-11-05 17:43:38
【问题描述】:

当你定义一个新的 Mongoose Schema 时,有什么方法可以设置一个“不可修改”设置的字段(例如类型、必需等)?这意味着一旦创建了新文档,就无法更改此字段。

例如,像这样的:

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

【问题讨论】:

    标签: node.js mongoose


    【解决方案1】:

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

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

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


    比 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
      }
    });
    

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

    【讨论】:

      【解决方案2】:

      您只能在 userSchema.pre save 中使用 Mongoose:

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

      【讨论】:

        【解决方案3】:

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

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

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

        1. 更新
        2. UpdateOne
        3. FindOneAndUpdate
        4. UpdateMany
        5. 重新保存

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

        插件还将更新选项处理为 $set、$inc 等。

        【讨论】:

          【解决方案4】:

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

          虽然在使用更新时会将值转换为相应的类型,但以下内容不适用:
          - 默认值
          - 二传手
          - 验证器
          - 中间件

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

          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 } 形式的附加“选项”参数调用任何更新函数(例如“findByIdAndUpdate”和朋友),例如:

          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() 或使用指定的验证选项参数更新函数时这样做。

          【讨论】:

            【解决方案5】:

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

            npm install mongoose-immutable --save
            

            然后使用它:

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

            【讨论】:

              猜你喜欢
              • 2012-11-13
              • 1970-01-01
              • 1970-01-01
              • 2013-01-26
              • 2018-12-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多