目前我有两个几乎相同的模式:
var userSchema = mongoose.Schema({
email: {type: String, unique: true, required: true, validate: emailValidator},
passwordHash: {type: String, required: true},
firstname: {type: String, validate: firstnameValidator},
lastname: {type: String, validate: lastnameValidator},
phone: {type: String, validate: phoneValidator},
});
和
var adminSchema = mongoose.Schema({
email: {type: String, unique: true, required: true, validate: emailValidator},
passwordHash: {type: String, required: true},
firstname: {type: String, validate: firstnameValidator, required: true},
lastname: {type: String, validate: lastnameValidator, required: true},
phone: {type: String, validate: phoneValidator, required: true},
});
他们唯一的区别在于验证:用户不需要名字,姓氏或电话 . 但是,管理员必须定义这些属性 .
不幸的是,上面的代码不是很干,因为它们几乎相同 . 因此,我想知道是否有可能基于 userSchema
构建 adminSchema
. 例如 . :
var adminSchema = mongoose.Schema(userSchema);
adminSchema.change('firstname', {required: true});
adminSchema.change('lastname', {required: true});
adminSchema.change('phone', {required: true});
显然这只是伪代码 . 这样的事情可能吗?
另一个非常相似的问题是,是否可以基于另一个创建新模式,并为其添加更多属性 . 例如:
var adminSchema = mongoose.Schema(userSchema);
adminSchema.add(adminPower: Number);
8 回答
有些人在其他地方suggested using utils.inherits来扩展模式 . 另一种简单的方法是简单地设置一个带有设置的对象并从中创建Schema,如下所示:
虽然它有点难看,因为你正在修改同一个对象 . 此外,我希望能够扩展插件和方法等 . 因此,我首选的方法如下:
这恰好回答了你的第二个问题 yes, you can add() fields . 因此,要修改Schema的某些属性,上述函数的修改版本将解决您的问题:
Mongoose 3.8.1现在支持歧视者 . 一个样本,从这里:http://mongoosejs.com/docs/api.html#model_Model.discriminator
您可以扩展原始 Schema#obj :
例:
或者使用此npm模块使用相同的方法:
检查github repo https://github.com/doasync/mongoose-extend-schema
要添加到此讨论中,您还可以使用自定义基础架构定义覆盖mongoose.Schema . 为了代码兼容性,添加允许在没有
new
的情况下实例化Schema的if语句 . 虽然这很方便,但在公共包中执行此操作之前要三思而后行 .我刚刚发表了mongoose-super npm module . 虽然我做了一些测试,但仍处于试验阶段 . 我很想知道它是否适合我的SO用户的应用程序!
该模块提供了inherit()便捷函数,该函数基于父模型和子模式扩展返回子Mongoose.js模型 . 它还使用super()方法扩充模型以调用父模型方法 . 我添加了这个功能,因为它是我在其他扩展/继承库中遗漏的东西 .
继承便利功能只使用discriminator method .
所有这些答案看起来都相当复杂,扩展辅助函数或扩展方法应用于模式或使用插件/鉴别器 . 我使用了以下解决方案,它简单,干净且易于使用 . 它定义了基本模式的蓝图,然后使用蓝图构建实际模式:
foo.blueprint.js
foo.schema.js
bar.schema.js
您可以按原样使用原始模式的蓝图,并使用
Object.assign
,您可以以任何方式扩展蓝图,而无需修改同一对象 .我没有要求歧视,因为我试图扩展子文档模式,无论如何都存储为父文档的一部分 .
我的解决方案是将“扩展”方法附加到作为基本模式的模式,以便您可以使用基本模式本身或基于它生成新模式 .
ES6代码如下:
您现在可以按原样使用此架构,或根据需要“扩展”它:
在这种情况下,扩展会创建一个全新的Schema定义 .
您可以创建一个Schema Factory函数,该函数接受模式定义和可选模式选项,然后将传递的模式定义和选项与要在模式之间共享的模式字段和选项合并 . 说明此示例(假设您要共享或扩展具有字段
email
和is_verified
以及启用timestamps
选项的架构):然后可以使用以下命令调用
SchemaFactory
函数:现在
UserSchema
和AdminSchema
将包含email
和is_verified
字段以及启用了timestamps
选项,以及传递的架构字段和选项 .