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
8.9.7
Node.js version
20.18.0
MongoDB server version
8.0.4
Typescript version (if applicable)
No response
Description
After updating a discriminator key in a document with schema discriminators and getters, the Document includes the fields for the current discriminator, as expected. However, Document.toObject() returns all fields, including those defined in a different discriminator schema, but only applies getters to the fields matching the current discriminator.
Steps to Reproduce
The following script will fail when checking the discriminator fields. In particular, the Document contains only the fields relevant to the discriminator, but the object returned by Document.toObject() contains all fields, including those for the other discriminator schema.
const conn = mongoose.createConnection(..);
const baseType = 'baseType';
const type1Key = 'Type1';
const type2Key = 'Type2';
const baseSchema = new mongoose.Schema({
field: String,
key: String,
}, {discriminatorKey: 'key', toObject: {getters: true}});
const dSchema1 = new mongoose.Schema({
field1: {
type: String,
get(value) {
return `${value} transformed`;
},
},
});
const dSchema2 = new mongoose.Schema({
field2: {
type: String,
get(value) {
return `${value} transformed`;
},
},
});
baseSchema.discriminator(type1Key, dSchema1);
baseSchema.discriminator(type2Key, dSchema2);
const TestModel = conn.model(baseType, baseSchema);
const field = 'field val';
const field1 = 'field1 val';
const field1Transformed = `${field1} transformed`;
const cdm = new TestModel({
key: type1Key,
field,
field1,
});
let cd = await cdm.save();
assert.equal(cd.field2, undefined);
assert.equal(cd.field1, field1Transformed);
cd = cd.toObject();
assert.equal(cd.field, field);
assert.equal(cd.key, type1Key);
assert.equal(cd.field1, field1Transformed);
assert.equal(cd.field2, undefined);
const field2 = 'field2 val';
const field2Transformed = `${field2} transformed`;
await TestModel.updateOne(
{ _id: cd._id },
{
key: type2Key,
field2,
},
{overwriteDiscriminatorKey: true},
);
let cd2 = await TestModel.findById(cd._id);
assert.equal(cd2.field2, field2Transformed);
assert.equal(cd2.field1, undefined);
cd2 = cd2.toObject();
assert.equal(cd2.field, field);
assert.equal(cd2.key, type2Key);
assert.equal(cd2.field2, field2Transformed);
assert.equal(cd2.field1, undefined);
conn.deleteModel(baseType);
Expected Behavior
As shown in the script above, since a Document with a discriminator includes only the fields relevant to the currently set discriminator key (prior to calling toObject()), I would expect the object returned by toObject() to also only include those fields defined in that discriminator schema.
If all fields must be returned by toObject() (even those not relevant to the current discriminator schema) I would expect all getters to have been called.