Data types and field validation
Data Type Basics
Mongoose provides a variety of data types for defining model fields. The most commonly used basic types include:
- String: String type
- Number: Numeric type
- Date: Date type
- Boolean: Boolean type
- Buffer: Binary data type
- ObjectId: MongoDB document ID
- Array: Array type
- Mixed: Mixed type
const userSchema = new mongoose.Schema({
name: String,
age: Number,
isActive: Boolean,
createdAt: Date,
hobbies: Array,
profile: Object
});
Field Validation Mechanism
Mongoose validators automatically execute before saving documents. Built-in validators include:
- required: Required field validation
- min/max: Numeric range validation
- enum: Enum value validation
- match: Regex matching validation
- validate: Custom validation function
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']
}
});
Custom Validators
More complex validation logic can be defined using the validate
property:
const userSchema = new mongoose.Schema({
email: {
type: String,
validate: {
validator: function(v) {
return /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/.test(v);
},
message: props => `${props.value} is not a valid email address`
}
},
age: {
type: Number,
validate: {
validator: function(v) {
return v >= 18 && v <= 120;
},
message: 'Age must be between 18 and 120'
}
}
});
Asynchronous Validation
For validations requiring asynchronous operations, return a 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: 'Username already exists'
}
}
});
Nested Object Validation
Validation rules can also be applied to nested objects:
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
});
Array Validation
Array fields can validate element types and quantities:
const postSchema = new mongoose.Schema({
tags: {
type: [String],
validate: {
validator: function(v) {
return v.length > 0 && v.length <= 5;
},
message: 'Number of tags must be between 1 and 5'
}
},
comments: [{
text: String,
author: String,
createdAt: { type: Date, default: Date.now }
}]
});
Error Handling
Validation failures throw ValidationError
, which can be caught and handled:
const newUser = new User({ email: 'invalid-email' });
newUser.save()
.then(doc => console.log(doc))
.catch(err => {
if (err instanceof mongoose.Error.ValidationError) {
console.error('Validation error:', err.errors);
} else {
console.error('Other error:', err);
}
});
Custom Error Messages
Custom error messages can be specified for each validation type:
const bookSchema = new mongoose.Schema({
title: {
type: String,
required: [true, 'Title cannot be empty'],
minlength: [3, 'Title must be at least 3 characters'],
maxlength: [100, 'Title cannot exceed 100 characters']
},
isbn: {
type: String,
match: [/^\d{3}-\d{10}$/, 'ISBN format should be XXX-XXXXXXXXXX']
}
});
Conditional Validation
Some field validations may depend on other field values:
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: 'Credit card payment requires a 16-digit card number'
}
}
});
Validation Middleware
Use pre
hooks to perform additional validation before saving:
userSchema.pre('save', function(next) {
if (this.isModified('password') && this.password.length < 8) {
throw new Error('Password must be at least 8 characters');
}
next();
});
Disabling Validation
Validation can be skipped in certain cases:
// Skip all validation
doc.save({ validateBeforeSave: false });
// Skip validation for specific paths
doc.save({ validateModifiedOnly: true });
Custom Types
Custom SchemaType extensions can be created:
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
上一篇:Schema的定义与结构
下一篇:自定义验证器与错误处理