Currently I have two almost identical schemas:
var userSchema = mongoose.Schema({
email: {type: String, unique: true, required: true, validate: emailVal
Mongoose 3.8.1 now has support for Discriminators. A sample, from here: http://mongoosejs.com/docs/api.html#model_Model.discriminator
function BaseSchema() {
Schema.apply(this, arguments);
this.add({
name: String,
createdAt: Date
});
}
util.inherits(BaseSchema, Schema);
var PersonSchema = new BaseSchema();
var BossSchema = new BaseSchema({ department: String });
var Person = mongoose.model('Person', PersonSchema);
var Boss = Person.discriminator('Boss', BossSchema);
I didn't require discrimination, as I was trying to extend sub document schema's which are stored as a part of a parent document anyway.
My solution was to append an "extend" method to the schema that is the base schema, so that you can either use the base schema itself or generate a new schema based on it.
ES6 code follows:
'use strict';
//Dependencies
let Schema = require('mongoose').Schema;
//Schema generator
function extendFooSchema(fields, _id = false) {
//Extend default fields with given fields
fields = Object.assign({
foo: String,
bar: String,
}, fields || {});
//Create schema
let FooSchema = new Schema(fields, {_id});
//Add methods/options and whatnot
FooSchema.methods.bar = function() { ... };
//Return
return FooSchema;
}
//Create the base schema now
let FooSchema = extendFooSchema(null, false);
//Expose generator method
FooSchema.extend = extendFooSchema;
//Export schema
module.exports = FooSchema;
You can now use this schema as is, or "extend" it as needed:
let BazSchema = FooSchema.extend({baz: Number});
Extension in this case creates a brand new Schema definition.
To add to this discussion, you can also override mongoose.Schema with a custom base schema definition. For code compatibility, add the if statement that allows a Schema to be instantiated without new. While this can be convenient, think twice before doing this in a public package.
var Schema = mongoose.Schema;
var BaseSyncSchema = function(obj, options) {
if (!(this instanceof BaseSyncSchema))
return new BaseSyncSchema(obj, options);
Schema.apply(this, arguments);
this.methods.update = function() {
this.updated = new Date();
};
this.add({
updated: Date
});
};
util.inherits(BaseSyncSchema, Schema);
// Edit!!!
// mongoose.Schema = BaseSyncSchema; <-- Does not work in mongoose 4
// Do this instead:
Object.defineProperty(mongoose, "Schema", {
value: BaseSyncSchema,
writable: false
});