Closed
Description
Prerequisites
- I have written a descriptive issue title
- I have searched existing issues to ensure the bug has not already been reported
Mongoose version
7.5.3
Node.js version
18.16
MongoDB server version
6.0.5
Typescript version (if applicable)
No response
Description
When defining a discriminated schema A that has a field which is discriminated schema B, after applying the discriminators at the schema level and instantiating an object of schema A, the types of B within it will always be of the default base type.
If you apply the discriminators for schema B directly on the path, it works as expected. This issue also happens if schema A has a subtype that self-references A. I am not sure how easy it is to convery through text, but I hope the code example makes it clear!
Steps to Reproduce
'use strict';
const mongoose = require('mongoose');
const { Schema } = mongoose;
const baseNestedDiscriminated = new Schema({
type: { type: Number, required: true },
}, { discriminatorKey: "type" });
class BaseClass {
type = 1;
whoAmI() {
return "I am baseNestedDiscriminated";
}
}
baseNestedDiscriminated.loadClass(BaseClass);
class NumberTyped extends BaseClass {
type = 3;
whoAmI() {
return "I am NumberTyped";
}
}
class StringTyped extends BaseClass {
type = 4;
whoAmI() {
return "I am StringTyped";
}
}
baseNestedDiscriminated.discriminator(1, new Schema({}).loadClass(NumberTyped));
baseNestedDiscriminated.discriminator("3", new Schema({}).loadClass(StringTyped));
const outerDiscriminatedSchema = new Schema({
type: { type: Number, required: true },
}, { discriminatorKey: "type" });
const containsNestedSchema = new Schema({
nestedDiscriminatedTypes: { type: [baseNestedDiscriminated], required: true },
})
// If you uncomment these, the example works as expected
//containsNestedSchema.path("nestedDiscriminatedTypes").discriminator(1, new Schema({}).loadClass(NumberTyped));
//containsNestedSchema.path("nestedDiscriminatedTypes").discriminator("3", new Schema({}).loadClass(StringTyped));
class ContainsNested {
nestedDiscriminatedTypes = [];
type = 1;
whoAmI() {
return "I am ContainsNested";
}
}
containsNestedSchema.loadClass(ContainsNested);
outerDiscriminatedSchema.discriminator(1, containsNestedSchema);
const secondModel = mongoose.model("containsNestedSchema", containsNestedSchema);
const containerModel = mongoose.model("container", new Schema({items: [baseNestedDiscriminated]}));
void async function main()
{
await mongoose.connect("mongodb://127.0.0.1:27017/example");
mongoose.connection.db.dropDatabase();
let instance = await containerModel.create({ items: [{type: 1}] }); // "I am NumberTyped" - Works
console.log(instance.items[0].whoAmI());
instance = await containerModel.create({ items: [{type: "3"}] }); // "I am StringTyped" Works
console.log(instance.items[0].whoAmI());
instance = await secondModel.create({ type: 1, nestedDiscriminatedTypes: [{type: 1}, {type: "3"}] });
console.log(instance.whoAmI()); // "I am ContainsNested" - Works
instance.nestedDiscriminatedTypes.forEach(item => console.log(item.whoAmI()));
// Expected:
// I am NumberTyped
// I am StringTyped
// Actual:
// I am baseNestedDiscriminated
// I am baseNestedDiscriminated
mongoose.disconnect();
}();
Expected Behavior
Shown in the code example, once discriminators are applied to a schema, the discriminators should always run wherever the schema is.