在定义模型的时候,mongoose 提供了常用的基础数据类型,有 String,Number,Date,Buffer,Boolean,Mixied,ObjectId,Array,虽然这些数据类型满足了大部分业务场景。但是在某一些场景还是需要更细粒度控制,例如定义一个 age(年龄)字段,这个字段限制大于 0 小于 100,就可以自定义一个类型,而不需要在每个 controller 去判断这些字段

自定义一个 mongoose 的数据类型,只需要继承 mongoose.schemaType,实现 cast 方法

const mongoose = require('mongoose');
function Age(key, options) {
mongoose.SchemaType.call(this, key, options, 'Age');
}
Age.prototype = Object.create(mongoose.SchemaType.prototype);
/**
* 参数可以是任意类型的数据,如果数据类型不匹配,抛出错误
* @param val
* @returns {number}
*/
Age.prototype.cast = function (val) {
let _val = Number(val);
if (isNaN(_val)) {
throw new Error('Age: ' + val + ' 不是数字');
}
if (val < 0 || val > 100) {
throw new Error('Age: ' + val + '超过范围');
}
return _val;
};
// 添加到Schema.Types
mongoose.Schema.Types.Age = Age;

定义 model 的时候使用自定义类型

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const Types = Schema.Types;
let testSchema = new Schema({
age: Types.Age, // mongoose.Schema.Types
});
mongoose.model('test', testSchema);

当 age 范围在 0-100 的时候我们是能准确保存的,当不在这范围内我们可以通过err.errors[字段].reason.message获取上面抛出的错误

require('../model/mongoose-init');
const mongoose = require('mongoose');
const Test = mongoose.model('test');
var test = new Test({
age: 122,
});
test
.save()
.then((ret) => {
console.log(ret);
})
.catch((err) => {
// 获取失败的原因
console.log(err.errors['age'].reason.message);
});