在定义模型的时候,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);
});