将 Mongoose 模式字段设为只读

DSh*_*ltz 4 mongoose mongodb node.js

我有一个猫鼬“用户”模式,其中一个字段需要是只读的。(“帐户”字段可以在外部更新,因此我不希望对用户的更新覆盖更改。)

var UserSchema = new Schema({
firstName: {
    type: String,
    trim: true,
    default: '',
    validate: [validateLocalStrategyProperty, 'Please fill in your first name']
},
lastName: {
    type: String,
    trim: true,
    default: '',
    validate: [validateLocalStrategyProperty, 'Please fill in your last name']
},
displayName: {
    type: String,
    trim: true
},
email: {
    type: String,
    trim: true,
    default: '',
    validate: [validateLocalStrategyProperty, 'Please fill in your email'],
    match: [/.+\@.+\..+/, 'Please fill a valid email address']
},
username: {
    type: String,
    unique: 'Username already exists',
    required: 'Please fill in a username',
    trim: true
},
password: {
    type: String,
},
accounts: [{
        account_hash: {type: String},
        account_name: {type: String}        
    }],

updated: {
    type: Date
},
created: {
    type: Date,
    default: Date.now
}
}
Run Code Online (Sandbox Code Playgroud)

我已经看到建议将该字段设为虚拟的答案,但是在保存时,该字段会从 Mongo 中删除。是否有一种简单的方法可以将 Mongoose 模式中的特定字段设为只读?

小智 7

使用最新版本的 Mongoose,您可以将 'immutable' 设置为要不可变的字段上的属性。你可以在这里阅读更多Mongoose immutable

所以你可以做类似的事情

const schema = new Schema({
  name: { type: String, immutable: true },
  age: Number
});

const Model = mongoose.model('Test', schema);

await Model.create({ name: 'test' });
const doc = await Model.findOne();

doc.isNew; // false
doc.name = 'new name';
doc.name; // 'test', because `name` is immutable
Run Code Online (Sandbox Code Playgroud)

这样做的缺点是您的用户不会收到错误消息,让他们知道他们正在尝试更新或已更新的字段是只读的


Akr*_*ion 5

在我看来,最好的办法是在pre 中间件save/update

您可以检查您不想更改的字段是否正在更改,isModified并简单地抛出有关您的字段只能从那里读取的错误:

someSchema.pre('save', function(next) { 
  if(this.isModified('someField')) {
    throw 'someField is read only!'
  }
  else {
    next();
  }
});
Run Code Online (Sandbox Code Playgroud)

对于更新,您应该通过获取更新this.getUpdate()并查看您的字段。