实现 Mongoose Schema 间继承
在创建数据库模型时我们希望这些模型能够互相继承或扩展, 例如一个银行网站可能所有模型都需要实现逻辑删除、 都需要记录创建人、最后修改人,以及删除人的信息。 通常可以通过扩展(比如 mixin)和继承(inherit)两种方式来实现。
对于小规模网站(比如 20 个模型以下)来讲, 继承的方式已经足够通用而且继承的代码复用方式编写代码更加方便。 Mongoose 并未直接地提供改选项,本文实现一个基本的模型间继承关系。
实现机制
在 Mongoose 中,Schema 实例是通过 mongoose.Schema
建立的。
因此为了 Schema 间的继承关系,我们需要一个 BaseSchema
先继承自 mongoose.Schema
,
再让其他 Schema 例如 UserSchema
继承自 BaseSchema
。
本文采取传统的 JavaScript 原型继承方式来实现模型的继承关系。
我们希望 UserSchema
拥有 BaseSchema
的全部属性和方法,
同时 UserSchema
的构造参数仍然可以直接传递给 mongoose.Schema
。
util.inherits
使用 util.inherits(constructor, superConstructor)
实现父子模型的继承关系:
util.inherits(BaseSchema, mongoose.Schema);
其中 util.inherits
的实现方式就是原型继承:
将当前对象 constructor
的 prototype
属性设置为 superConstructor
创建的一个实例。
即:
constructor.prototype = Object.create(superConstructor.prototype);
// 事实上情况要复杂得多,目前 Node.js 中以 Object.setPrototypeOf 实现..
注意,
util.inherits
已经不赞成使用了,应使用class
和extend
来代替。 且 两者的语义并不兼容。 但为了兼容目前的代码,本文仍然借助util.inherits
来实现继承。
Schema.apply
UserSchema
除了继承 BaseSchema
,还需要将它的构造参数通过 BaseSchema
传递给 mongoose.Schema
。这一过程尤为简单:
function BaseSchema(){
mongoose.Schema.apply(this, arguments);
}
基类模型代码
这里给出完整的 BaseSchema
声明,由于 mongoose.Schema 只有两个参数因此
我们用 call
来更方便地完成任务。
// file: models/base.js
const _ = require('lodash');
const mongoose = require('mongoose');
const util = require('util');
const defaultOptions = ;
function BaseSchema(properties, options) {
properties = _.defaults(properties, {
// Base Properties
createdBy: {
type: String,
ref: 'User'
},
updatedBy: {
type: String,
ref: 'User'
},
deletedBy: {
type: String,
ref: 'User'
}
});
options = _.defaults(options, {
// Base Options
timestamps: true
});
mongoose.Schema.call(this, properties, options);
// Base Plugins and Virtuals
this.plugin(...);
this.virtual('...');
}
util.inherits(BaseSchema, mongoose.Schema);
module.exports = BaseSchema;
子类模型代码
// models/user.js
const BaseSchema = require('./base.js');
var UserSchema = new BaseSchema({
name: String,
role: {
type: String,
default: 'user',
enum: ['admin', 'user']
}
}, {
autoIndex: false
});
// User Plugins
UserSchema.plugin(...);
module.exports = mongoose.model('User', UserSchema);
本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可,转载注明来源即可: https://harttle.land/2016/09/26/mongoose-base-schema.html。如有疏漏、谬误、侵权请通过评论或 邮件 指出。