Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

findOneAndUpdate discriminator key does not survive projection #11546

Closed
OoDeLally opened this issue Mar 20, 2022 · 4 comments
Closed

findOneAndUpdate discriminator key does not survive projection #11546

OoDeLally opened this issue Mar 20, 2022 · 4 comments
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@OoDeLally
Copy link

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
When using a discriminator key, all mongoose methods return the discriminator key in addition of the provided projection.
e.g. A {name: 1} projection would still result in a document including the discriminator {name: 'Batman', kind: 'Hero'}.

findOneAndUpdate differs from this behavior, in that it does not include the discriminator key.
e.g. {name: 1} projection results in {name: 'Batman'}.

mongoose 6.1.5

@IslandRhythms IslandRhythms added the needs repro script Maybe a bug, but no repro script. The issue reporter should create a script that demos the issue label Mar 21, 2022
@vkarpov15 vkarpov15 added this to the 6.2.12 milestone Mar 27, 2022
@IslandRhythms
Copy link
Collaborator

IslandRhythms commented Mar 28, 2022

@OoDeLally Modify the script below to demonstrate your issue. If I had to guess, you were doing the findOneAndUpdate operation on your Main model and not the discriminator.

const mongoose = require('mongoose');

const testSchema = new mongoose.Schema({
    name: String,
});

const Test = mongoose.model('Test', testSchema);

const TestScrim = Test.discriminator('TestScrim', new mongoose.Schema({
    age: Number
}, {discriminatorKey: 'kind'}));

async function run() {
await mongoose.connect('mongodb://localhost:27017');
await mongoose.connection.dropDatabase();

await Test.create({
    name: 'Batman'
});

await TestScrim.create({
    name: 'Nightwing',
    age: 18
});

await TestScrim.create({
    name: 'Batman',
    age: 36
})

console.log(await Test.find({name: 'Batman'}, {name: 1}));

const result = await TestScrim.findOneAndUpdate({age: 36}, {name: 'batman'}, {name: 1, new: true})

console.log(result);
}
run();

@IslandRhythms IslandRhythms added can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. and removed needs repro script Maybe a bug, but no repro script. The issue reporter should create a script that demos the issue labels Mar 28, 2022
@OoDeLally
Copy link
Author

OoDeLally commented Apr 2, 2022

Hello @IslandRhythms, thank you for your prompt answer.

I found out that it happens when the discriminator key is part of the schema:

const mongoose = require('mongoose');

const baseSchema = new mongoose.Schema({
    kind: { type: String }, // Comment out to get back to normal behavior.
    name: String,
}, {discriminatorKey: 'kind'});

const BaseModel = mongoose.model('Base', baseSchema);

const childSchema = new mongoose.Schema({
    age: Number
}, { discriminatorKey: 'kind' });

const ChildModel = BaseModel.discriminator('Child', childSchema);

async function run() {
    await mongoose.connect('mongodb://localhost:27017');
    await mongoose.connection.dropDatabase();

    await ChildModel.create({
        name: 'Batman',
        age: 36
    })

    const findResult = await BaseModel.findOne({age: 36}, {name: 1})
    console.log('findResult');
    console.log(findResult);

    const findOneAndUpdateResult = await BaseModel.findOneAndUpdate({age: 36}, {name: 'batman'}, {new: true, projection: { name: 1 }})
    console.log('findOneAndUpdateResult');
    console.log(findOneAndUpdateResult);

    await mongoose.connection.close();
}

run();

What is mongoose's recommendation regarding adding the discriminator to the schema ? I use typescript enums as discriminator values, and therefore it is useful for me to get the validation.

@IslandRhythms
Copy link
Collaborator

What is mongoose's recommendation regarding adding the discriminator to the schema?

If you mean defining the discriminator on the schema, it is a feature that will be shipped in the nearby future, possible in mongoose 6.3.
If not, here is the docs regarding discriminators
https://mongoosejs.com/docs/discriminators.html

@vkarpov15 vkarpov15 modified the milestones: 6.3.1, 6.3.2 Apr 20, 2022
@vkarpov15 vkarpov15 added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. and removed can't reproduce Mongoose devs have been unable to reproduce this issue. Close after 14 days of inactivity. labels Apr 20, 2022
@vkarpov15
Copy link
Collaborator

In #4629 we made it so that Model.find() and Model.findOne() always add the discriminator key to the projection. In 6.3.2, we'll have a fix that will let you do:

const findResult = await BaseModel.findOne({age: 36}, {name: 1, __t: 0})

to opt out of automatically selecting the discriminator key.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
Development

No branches or pull requests

3 participants