阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 数据类型与字段验证

数据类型与字段验证

作者:陈川 阅读数:21956人阅读 分类: MongoDB

数据类型基础

Mongoose 提供了丰富的数据类型用于定义模型字段。最常用的基本类型包括:

  • String:字符串类型
  • Number:数字类型
  • Date:日期类型
  • Boolean:布尔类型
  • Buffer:二进制数据类型
  • ObjectId:MongoDB文档ID
  • Array:数组类型
  • Mixed:混合类型
const userSchema = new mongoose.Schema({
  name: String,
  age: Number,
  isActive: Boolean,
  createdAt: Date,
  hobbies: Array,
  profile: Object
});

字段验证机制

Mongoose 的验证器在保存文档前自动执行。内置验证器包括:

  1. required:必填验证
  2. min/max:数值范围验证
  3. enum:枚举值验证
  4. match:正则匹配验证
  5. validate:自定义验证函数
const productSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    minlength: 3,
    maxlength: 50
  },
  price: {
    type: Number,
    min: 0,
    max: 10000
  },
  category: {
    type: String,
    enum: ['electronics', 'clothing', 'food']
  }
});

自定义验证器

通过 validate 属性可以定义更复杂的验证逻辑:

const userSchema = new mongoose.Schema({
  email: {
    type: String,
    validate: {
      validator: function(v) {
        return /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(v);
      },
      message: props => `${props.value} 不是有效的邮箱地址`
    }
  },
  age: {
    type: Number,
    validate: {
      validator: function(v) {
        return v >= 18 && v <= 120;
      },
      message: '年龄必须在18到120岁之间'
    }
  }
});

异步验证

对于需要异步操作的验证,可以返回 Promise:

const usernameSchema = new mongoose.Schema({
  username: {
    type: String,
    validate: {
      validator: function(v) {
        return new Promise((resolve, reject) => {
          User.findOne({ username: v })
            .then(user => resolve(!user))
            .catch(err => reject(err));
        });
      },
      message: '用户名已存在'
    }
  }
});

嵌套对象验证

嵌套对象也可以应用验证规则:

const addressSchema = new mongoose.Schema({
  street: { type: String, required: true },
  city: { type: String, required: true },
  zipCode: {
    type: String,
    validate: {
      validator: function(v) {
        return /^\d{5}(-\d{4})?$/.test(v);
      }
    }
  }
});

const customerSchema = new mongoose.Schema({
  name: String,
  address: addressSchema
});

数组验证

数组字段可以验证元素类型和数量:

const postSchema = new mongoose.Schema({
  tags: {
    type: [String],
    validate: {
      validator: function(v) {
        return v.length > 0 && v.length <= 5;
      },
      message: '标签数量必须在1到5个之间'
    }
  },
  comments: [{
    text: String,
    author: String,
    createdAt: { type: Date, default: Date.now }
  }]
});

错误处理

验证失败时会抛出 ValidationError,可以捕获并处理:

const newUser = new User({ email: 'invalid-email' });

newUser.save()
  .then(doc => console.log(doc))
  .catch(err => {
    if (err instanceof mongoose.Error.ValidationError) {
      console.error('验证错误:', err.errors);
    } else {
      console.error('其他错误:', err);
    }
  });

自定义错误消息

可以为每种验证类型指定自定义错误消息:

const bookSchema = new mongoose.Schema({
  title: {
    type: String,
    required: [true, '书名不能为空'],
    minlength: [3, '书名至少3个字符'],
    maxlength: [100, '书名最多100个字符']
  },
  isbn: {
    type: String,
    match: [/^\d{3}-\d{10}$/, 'ISBN格式应为XXX-XXXXXXXXXX']
  }
});

条件验证

某些字段的验证可能需要依赖其他字段的值:

const orderSchema = new mongoose.Schema({
  paymentMethod: {
    type: String,
    enum: ['credit', 'paypal', 'bank']
  },
  creditCardNumber: {
    type: String,
    validate: {
      validator: function(v) {
        return this.paymentMethod !== 'credit' || 
              /^\d{16}$/.test(v);
      },
      message: '信用卡支付需要16位卡号'
    }
  }
});

验证中间件

使用 pre 钩子可以在保存前执行额外验证:

userSchema.pre('save', function(next) {
  if (this.isModified('password') && this.password.length < 8) {
    throw new Error('密码至少需要8个字符');
  }
  next();
});

禁用验证

在某些情况下可能需要跳过验证:

// 跳过所有验证
doc.save({ validateBeforeSave: false });

// 跳过特定路径验证
doc.save({ validateModifiedOnly: true });

自定义类型

可以创建自定义的 SchemaType 扩展:

class TruncateString extends mongoose.SchemaType {
  constructor(key, options) {
    super(key, options, 'TruncateString');
    this.maxLength = options.maxLength || 100;
  }

  cast(val) {
    let _val = String(val);
    if (_val.length > this.maxLength) {
      _val = _val.substring(0, this.maxLength);
    }
    return _val;
  }
}

mongoose.Schema.Types.TruncateString = TruncateString;

const schema = new mongoose.Schema({
  excerpt: { type: TruncateString, maxLength: 50 }
});

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌