简体   繁体   中英

Mongoose discriminators, instantiate documents

We're using inherited schemas with Mongoose's discriminator functionality, which we implemented according to the documentation .

Through our REST API we want to POST documents of the different types and handle the logic with a common controller function.

Suppose, we have a REST method for creating a document, which can be either of super type GenericEvent , or sub types ClickedLinkEvent , or SignedUpEvent (to follow the example from the docs linked above). What I'm currently doing is something like:

var GenericEventModel = require('GenericEventModel');
var ClickedLinkEventModel = require('ClickedLinkEvent');
var SignedUpEventModel = require('SignedUpEvent');

// REST logic for creating a document of a specific type
module.exports.createEvent = function(req, res, next) {
   var modelType = req.params.type; // as provided via REST parameter
   var Model = getModel(modelType); // get the appropriate model type
   new Model(req.body).save(next);
}

// TODO want to avoid this
function getMongooseModel(type) {
  switch (modelType) {
    case 'GenericEvent': return GenericEventModel;
    case 'ClickedLinkEvent': return ClickedLinkEventModel;
    case 'SignedUpEvent': return SignedUpEventModel;
    // and many more, needs to be extended, every time a new type is added …
  }
}

Having to manually curate the getMongooseModel function whenever a new model type is added seems rather error-prone, and I suspect other people who will be working on the code will simply forget about it.

So, my question: Is there an existing function in the Mongoose API which can give me the appropriate model for a given discriminator key by looking at all known sub schemas?

A better implementation should be to use an object instead of a switch.

var modelMap = {
  'GenericEvent': GenericEventModel,
  'ClickedLinkEvent': ClickedLinkEventModel,
  'SignedUpEvent': SignedUpEventModel
};

function getMongooseModel(type) {
  return modelList[type];
}

After that in order to avoid errors you can use Mongoose#plugin(fn, [opts]) in order to populate the modelMap object.

Or you can just use Mongoose#model(name, [schema], [collection], [skipInit]) .

Defines a model or retrieves it.

Something like this should work:

module.exports.createEvent = function(req, res, next) {
  var Model = mongoose.model(req.params.type);
  (new Model(req.body)).save(next);
}

With a proper declaration of your model class in mongoose, model name must match your request parameter of course.

var GenericEventModel = mongoose.model('GenericEvent', GenericEventModelSchema);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM