Mongoose: extending schemas

Tom picture Tom · Aug 19, 2013 · Viewed 37.5k times · Source

Currently I have two almost identical schemas:

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},

});

And

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},

});

Their only difference is in validation: Users do not need a firstname, lastname or phone. Admins however must have these properties defined.

Unfortunately the above code is not very DRY, as they're almost identical. Therefore I am wondering if it is possible to build an adminSchema based on the userSchema. E.g.:

var adminSchema = mongoose.Schema(userSchema);
adminSchema.change('firstname', {required: true});
adminSchema.change('lastname', {required: true});
adminSchema.change('phone', {required: true});

Obviously that's just pseudocode. Is something like this possible?

Another very similar question is if it is possible to create a new schema based on another, and add some more properties to it. For example:

var adminSchema = mongoose.Schema(userSchema);
    adminSchema.add(adminPower: Number);

Answer

regretoverflow picture regretoverflow · Nov 25, 2013

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);