Mongoose: Abstract base schemas for use exclusively with discriminators

Created on 14 Jul 2017  路  6Comments  路  Source: Automattic/mongoose

Do you want to request a feature or report a bug?

feature

It would be nice to have abstract schemas that you cannot instantiate, and instead must instantiate via discriminators.

var shapeSchema = new Schema({
  name: String
}, {
  discriminatorKey: "type",
  abstract: true // <----
});

var Shape = db.model('Shape', shapeSchema);
var Circle = Shape.discriminator('Circle', new Schema({ radius: Number }));

new Shape() would be invalid
Shape.create({type: "not a registered discriminator"}) would be invalid
Shape.create({type: "Circle"}) would be valid
new Circle() would be valid
Shape.find() would be valid

If you agree that this functionality would be useful, I can try to work on a PR.


Current workaround is to have a helper function used before Shape.create that makes sure the value for the discriminator key is allowed.

discussion new feature

Most helpful comment

Yeah that's a fair point, throwing an error seems sane. Can you implement this as a plugin? http://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins Should be pretty easy to just throw it in the lib/plugins folder

All 6 comments

I like the general idea, but how would abstract work if you set it on a schema you pass to discriminator()?

how would abstract work if you set it on a schema you pass to discriminator()

I think that should throw an error. (Can you think of a use case?) Unless someone is creating schemas at runtime, that would be a boot-time error that would be easy to spot and remedy.

Yeah that's a fair point, throwing an error seems sane. Can you implement this as a plugin? http://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins Should be pretty easy to just throw it in the lib/plugins folder

@zbjornson Did you ever manage to find time to implement this as a plugin?

@Faibk I haven't had a chance to yet, no. We use a static BaseModel.instantiate method currently to achieve this effect for now, something like this:

/**
 * Returns the model constructor based on the discriminator key __t.
 * @param v: object containing at least the discriminator key __t
 * @return function Model constructor
 */
Shape.statics.getModel = function (v, cb) {
    if (v.__t === undefined) {
        return cb(new Error("missing component type for component " + v));
    }
    if (!(v.__t in mongoose.models)) {
        return cb(new Error("'" + v.__t + "' is not a valid Shape type"));
    }
    var Model = mongoose.model(v.__t);
    cb(null, Model);
};

/**
 * Creates an instance of the component based on the discriminator key __t.
 * @param v: object containing the full model including the discriminator key __t.
 * @return Model
 */
Shape.statics.instantiate = function (v, cb) {
    Shape.getModel(v, function (e, Ctor) {
        if (e) return cb(e);
        cb(null, new Ctor(v));
    });
};

Something new about abstract schema ? I have exactly the same need than @zbjornson.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jeneser picture jeneser  路  3Comments

adamreisnz picture adamreisnz  路  3Comments

tarun1793 picture tarun1793  路  3Comments

p3x-robot picture p3x-robot  路  3Comments

simonxca picture simonxca  路  3Comments