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

Different behaviour of findOneAndReplace with strict option #13507

Closed
2 tasks done
iamKushagra opened this issue Jun 14, 2023 · 1 comment · Fixed by #13516
Closed
2 tasks done

Different behaviour of findOneAndReplace with strict option #13507

iamKushagra opened this issue Jun 14, 2023 · 1 comment · Fixed by #13516
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@iamKushagra
Copy link

iamKushagra commented Jun 14, 2023

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.2.1

Node.js version

14.17.3

MongoDB server version

6.0.5

Typescript version (if applicable)

No response

Description

Based on my analysis, it appears that there are some issues with the findOneAndReplace method when using the strict option. Specifically, the function using findOneAndUpdate method throws an error during execution, while the replace function using findOneAndReplace works without any problems.

Upon reviewing the situation, it seems that the {strict: 'throw'} option of findOneAndReplace is not overriding the {strict: true} property of the schema as it is intended to, similar to how it works in findOneAndUpdate. It is unclear why the {strict: 'throw'} option in findOneAndReplace is not being patched.

Error Message:

> put data
Connected to MongoDB
replace result: { _id: new ObjectId("64884ad808a564d77dc37bf7") }
> patch data
Connected to MongoDB
Error: StrictModeError: Field `x` is not in schema and strict mode is set to throw.
    at walkUpdatePath (/Users/kushagra/gridfs/node_modules/mongoose/lib/helpers/query/castUpdate.js:348:17)
    at castUpdate (/Users/kushagra/gridfs/node_modules/mongoose/lib/helpers/query/castUpdate.js:92:7)
    at model.Query._castUpdate (/Users/kushagra/gridfs/node_modules/mongoose/lib/query.js:4673:10)
    at model.Query._findOneAndUpdate (/Users/kushagra/gridfs/node_modules/mongoose/lib/query.js:3302:23)
    at model.Query.exec (/Users/kushagra/gridfs/node_modules/mongoose/lib/query.js:4404:28)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async update (/Users/kushagra/gridfs/index.js:53:21)
    at async /Users/kushagra/gridfs/index.js:78:29 {
  isImmutableError: false,
  path: 'x'
}

Sample Data

{
  _id: ObjectId("64884ad808a564d77dc37bf7"),
  title: 'abc'
},
{
  _id: ObjectId("64886aae08a564d77dc37bf8"),
  title: 'def'
}

Steps to Reproduce

Run the provided code.

const mongoose = require('mongoose');

// Define the schema for your data
const YourSchema = new mongoose.Schema({
    title: String,
    // ... add other properties as needed
}, { strict: true });

// Create the Mongoose model
const YourModel = mongoose.model('YourModel', YourSchema);

// Connect to your MongoDB database
async function colCon() {
    try {
        await mongoose.connect('mongodb://localhost:27017/your-database', {
            useNewUrlParser: true,
            useUnifiedTopology: true,
        });
        console.log('Connected to MongoDB');
        return YourModel;
    } catch (err) {
        console.error('Error connecting to MongoDB:', err);
        throw err;
    }
}

async function replace(newData = {}) {
    console.log('> put data');

    const condition = { title: 'abc' };
    try {
        const model = await colCon();
        const doc = await model.findOneAndReplace(  // not throwing error
            condition,
            newData,
            {
                returnDocument: 'after',
                strict: 'throw'
            }
        );
        return doc;
    } catch (err) {
        throw err;
    }
}

async function update(newData = {}) {
    console.log('> patch data');

    const condition = { title: 'def' };
    try {
        const model = await colCon();
        const doc = await model.findOneAndUpdate(  // throws error
            condition,
            newData,
            {
                returnDocument: 'after',
                strict: 'throw'
            }
        );
        return doc;
    } catch (err) {
        throw err;
    }
}

// Usage example
(async () => {
    try {
        const newData = {
            // title: 'New Title',
            x: 'x'
        };

        const putResult = await replace(newData);
        console.log('replace result:', putResult);

        const patchResult = await update(newData);
        console.log('update result:', patchResult);

        // Close the Mongoose connection when you're done
        mongoose.connection.close();
    } catch (err) {
        console.error('Error:', err);
    }
})();

Expected Behavior

Both the replace and update functions should work as intended by throwing the errors by overriding the option in the schema.

@vkarpov15 vkarpov15 added this to the 7.3.1 milestone Jun 14, 2023
@vkarpov15 vkarpov15 added the has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue label Jun 14, 2023
@IslandRhythms IslandRhythms added confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. and removed has repro script There is a repro script, the Mongoose devs need to confirm that it reproduces the issue labels Jun 15, 2023
@IslandRhythms
Copy link
Collaborator

I'm getting the same error however the replace result line is null instead of an objectID

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

Successfully merging a pull request may close this issue.

3 participants