首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >防止使用Mongoose架构修改字段

防止使用Mongoose架构修改字段
EN

Stack Overflow用户
提问于 2018-05-26 23:16:04
回答 5查看 5.8K关注 0票数 8

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

例如,如下所示:

代码语言:javascript
复制
var userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
    unmodifiable: true
  }
})
EN

回答 5

Stack Overflow用户

发布于 2019-06-30 23:18:12

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

代码语言:javascript
复制
const userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
    immutable: true
  }
});

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

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

代码语言:javascript
复制
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

票数 20
EN

Stack Overflow用户

发布于 2018-05-27 01:03:37

userSchema.pre save中,您只能对Mongoose执行此操作

代码语言:javascript
复制
if (this.isModified('modified query')) {
    return next(new Error('Trying to modify restricted data'));
}
return next();
票数 1
EN

Stack Overflow用户

发布于 2018-07-31 16:26:18

请注意,文档中明确指出,在使用标识符/名称为update的函数时,不会触发'pre‘中间件:

尽管在使用document.Model.findOne({ name: 'borne' }, function (err, doc) { if (err) .. doc.name = 'jason bourne'; doc.save(callback); })时,会将值强制转换为相应的类型,但以下内容不是

您需要这些功能,请使用传统的方法首先检索update

因此,要么使用上面的mongooseAPI,它可以触发中间件(就像desoares answer中的'pre‘),要么触发您自己的验证器,例如:

代码语言:javascript
复制
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),例如:

代码语言:javascript
复制
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));

您还可以以非标准的方式使用验证器函数,例如:

代码语言:javascript
复制
...
validator: function(value) {
  if(value != theOneAndOnlyName) {
    this.username = theOneAndOnlyName;
  }
  return true;
}
...

这不会抛出“ValidationError”,但会悄悄重写指定的值。只有在使用带有指定验证选项参数的save()或update函数时,它才会这样做。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50544198

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档