Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save thehme/be0774570eec8873cfc0c1ba3db6dd4a to your computer and use it in GitHub Desktop.
Save thehme/be0774570eec8873cfc0c1ba3db6dd4a to your computer and use it in GitHub Desktop.

I am using mongoose 5.3.6 and I am trying to share a common set of schema attributes for a model question, then based on a discriminator, use a schema that adds to the base schema.

The following schema is the working schema, where all question models have the samea attributes:

var SurveyQuestion = new Schema({
        questionId: {type: Number, required: true},
        question: {type: String, required: true, index: true},
        ...
}, {_id: false, versionKey: false});

var Translation = new Schema({
        language: {type: String, required: true},
        name: {type: String, required: true},
        questions: {type: [Question]}
});
    
var ParentSurvey = new Schema({
        name: {type: String, required: true, index: true},
        Translations: {type: [Translation]}
}, {timestamps: true, strict: 'throw'});

I would like to have a common base question schema, that I can use to create questions of different types, instead of keeping all the attributes of all questions in the same question model. Now, the question itself is an object embedded in an array of questions in a Translation object, which itself is also in an embedded array of translations in a ParentSurvey. The ParentSurvey is the collection this is all saved into.

In other to accomplish inheritance, I am using mongoose's discrimintators feature, but I am having issues with the changes not working. The link to the feature is at https://mongoosejs.com/docs/discriminators.html#embedded-discriminators-in-arrays

The changes I am making are:

var SurveyQuestionBaseOptions = {
        _id: false, 
        versionKey: false,
        discriminationKey: 'kind'
};

var SurveyQuestionBaseSchema = new Schema({
        question: {type: String, required: true, index: true},
        questionId: {type: Number, required: true},
        ...
}, SurveyQuestionBaseOptions);

var SurveyQuestionRatingScaleSchema = new Schema({
        isDiscrete: {type: Boolean, required: true, default: false}
}, SurveyQuestionBaseOptions);

this.SurveyQuestions = mongoose.model('SurveyQuestions', SurveyQuestionBaseSchema);
this.SurveyQuestionRatingScale = this.SurveyQuestions.discriminator('RatingScaleQuestion', SurveyQuestionRatingScaleSchema.clone());
...
SurveyTranslation.path('questions').discriminator('RatingScaleQuestion', SurveyQuestionRatingScaleSchema.clone());
    

When I post to my saved a translation, containing the question(s), and save this translation in the parent survey, I do not see the value isDiscriminate being passed in the mongoose command. I do see it being passed from the client to the server, so that value exists, but it seems the schema for the rating scale type question is not being picked up, even though a value for the discriminator kind is being passed and has the value of 'RatingScaleQuestion', i.e.

ParentSurveys.findOne({_id: req.body._parentSurvey}).exec(function(error, parentSurvey) {
        var translation = {
                name: req.body.name,
                language: req.body.language,
                ...
                questions: req.body.questions, // question has value `isDiscrete` and `kind`
        };
        
        parentSurvey.Translations.push(translation);    // translation with questions is added to parentSurvey
        parentSurvey.save().then(async () => {
        ...        
        // if I look at the parent survey saved, I see the question(s) added, but the `isDiscrete` value is not saved               

Am i missing something in the configuration of the discriminator? Perhaps this is not working yet, it seems there might be an issue open for this topic - Automattic/mongoose#6531

@thehme
Copy link
Author

thehme commented Jan 15, 2019

My issue with the code above was that I wrote discriminationKey: 'kind' instead of discriminatorKey: 'kind'. Hopefully this can help someone else. Type checking would have save me lots of time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment