mongoose自定义schema type之路
前言
mongoose是nodejs使用非常方便的一个操作mongodb的一个库,目前star已经过万。
但是其支持的类型很少,只有:
- String
- Number
- Date
- Buffer
- Boolean
- Mixed
- ObjectId
- Array
- Decimal128
这明显是不方便使用的,所以官方也提供了自定义type的接口。并且github上也有别人写好的插件可以使用,如long、Int32等
为了以后少写代码,提高代码复用,所以我阅读了Int32源码,学习怎么自定义schema类型。
Int32
源码:
'use strict';
const mongoose = require('mongoose');
const INT32_MAX = 0x7FFFFFFF; // 设定int32的范围
const INT32_MIN = -0x80000000;
class Int32 extends mongoose.SchemaType { // 继承mongoose.SchemaType
constructor(key, options) {
super(key, options, 'Int32'); // 调用父类构造器
}
/**
* Cast the given value to something that MongoDB will store as int32
* 将给定的值转换为MongoDB存储的int 32。
*
* @param {any} val
* @return {Number}
*/
cast(val) {
var _val = Number(val);
if (isNaN(_val)) { // NaN时,表示传入的val不是Number类型
throw new mongoose.SchemaType.CastError('Int32', //抛出错误
val + ' is not a number');
}
_val = Math.round(_val); // 四舍五入
if (_val < INT32_MIN || _val > INT32_MAX) { // 判断范围
throw new mongoose.SchemaType.CastError('Int32', val +
' is outside of the range of valid BSON int32s: ' + INT32_MAX + ' - ' +
INT32_MIN);
}
return _val;
}
}
Int32.prototype.$conditionalHandlers =
mongoose.Schema.Types.Number.prototype.$conditionalHandlers;
// 这句应该是继承了Number类型的$conditionalHandlers
Int32.INT32_BSON_TYPE = 16;
Int32.INT32_MAX = INT32_MAX;
Int32.INT32_MIN = INT32_MIN;
Int32.instance = 'Int32'; // 设置类型
mongoose.Schema.Types.Int32 = Int32; // 把Int32挂载到Schema的Types上去
module.exports = Int32; // export
大概懂了
- 实现一个类继承mongoose.SchemaType
- 实现构造器调用父类构造器
- 实现cast(val)函数,这个函数用来判断类型是否正确,并对数据进行处理,数据处理错误应该抛出父类的错误CastError
- 挂载父类的prototype.$conditionalHandlers
- 设置一些参数(可选)
- 设置instance
- 挂载到mongoose.Schema.Types
- export出去
实现一个自定义的Int类型
这里结合了eggjs定制了:
'use strict';
module.exports = app => {
const { mongoose } = app;
class Int extends mongoose.SchemaType { // 继承mongoose.SchemaType
constructor(key, options) {
super(key, options, 'Int'); // 调用父类构造器
}
cast(val) {
var _val = Number(val);
if (isNaN(_val)) {
throw new mongoose.SchemaType.CastError('Int', val + ' is not a number');
}
if (! Number.isInteger(_val)) {
throw new mongoose.SchemaType.CastError('Int', val + ' is not int');
}
return _val;
}
}
Int.prototype.$conditionalHandlers =
mongoose.Schema.Types.Number.prototype.$conditionalHandlers;
Int.instance = 'Int';
mongoose.Schema.Types.Int = Int;
};
输了个float类型,成功报错:
搞定。
什么时候自定义类型?
个人觉得如果这个类型不满足原子性就没必要自定义类型,因为哪怕你定义了也用不到多少次。
如果一个正则表达式就能解决,那么推荐使用match来匹配正则表达式,也别用自定义类型。match: /http:\/\/.*/
如果写两三行validate能搞定,那也没必要自定义类型。
validate: (data)=>{ // 自定义数据校验方法
return data.length >= 10;
}
如果滥用自定义类型会导致代码太过复杂,不易于维护。
有什么问题欢迎留言评论,看到会尽量回复的
版权声明
本文章由作者“衡于墨”创作,转载请注明出处,未经允许禁止用于商业用途
发布时间:2019年07月06日 14:31:18
备案号:
闽ICP备19015193号-1
关闭特效
评论区#
还没有评论哦,期待您的评论!
引用发言