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
My issue with the code above was that I wrote
discriminationKey: 'kind'
instead ofdiscriminatorKey: 'kind'
. Hopefully this can help someone else. Type checking would have save me lots of time.