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

Changing a schema path using schema.path significantly affects performance #15253

Closed
2 tasks done
mcat95 opened this issue Feb 12, 2025 · 1 comment · Fixed by #15256
Closed
2 tasks done

Changing a schema path using schema.path significantly affects performance #15253

mcat95 opened this issue Feb 12, 2025 · 1 comment · Fixed by #15256
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. performance
Milestone

Comments

@mcat95
Copy link

mcat95 commented Feb 12, 2025

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

Node.js version

v18.19.0

MongoDB server version

8.0.4

Typescript version (if applicable)

No response

Description

When using schema.path to add a SingleNested type to a preexisting schema, adds the new SingleNested children to the childSchemas schema property, regarding of whether it was already in the array. This affects save() operations on large documents, with deeply nested documents.

Multiple calls to the path method make the issue exponentially worse.

We've found that calling _gatherChildSchemas() is an effective workaround and fixes the issue.

Steps to Reproduce

const mongoose = require('mongoose');
const crypto   = require('crypto');

const RecursiveSchema = new mongoose.Schema({
  data: String,
});

const s = [ RecursiveSchema ];
RecursiveSchema.path('nested', s);

// If you comment the following line the issue goes away
RecursiveSchema.path('nested', s);

// If you uncomment the following lines the issue gets even worse
//RecursiveSchema.path('nested', s);
//RecursiveSchema.path('nested', s);

// Uncoment for a workaround
//RecursiveSchema._gatherChildSchemas();

const generateRecursiveDocument = (depth, curr = 0) => {
  return {
    name: `Document of depth ${curr}`,
    nested: depth > 0 ? new Array(3).fill().map(() => generateRecursiveDocument(depth-1, curr+1)) : [],
    data: crypto.randomBytes(128).toString('hex'),
  };
}

const main = async () => {
  console.log(mongoose.version)
  await mongoose.connect('mongodb://localhost/mongoose-test');
  const model = new mongoose.model('Recursive', RecursiveSchema);
  const data = generateRecursiveDocument(6);
  const doc = new model(data)
  console.time('Save time');
  await doc.save();
  console.timeEnd('Save time');
};

main().then(process.exit);

Expected Behavior

The save operation should not take more than 100ms, which is the case when you only call the path function once.

@vkarpov15 vkarpov15 added this to the 8.10.1 milestone Feb 12, 2025
@vkarpov15 vkarpov15 added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Feb 12, 2025
@mcat95
Copy link
Author

mcat95 commented Feb 13, 2025

Hello @vkarpov15,

Thanks for taking a look into this performance issue. We've found a very similar related issue and reported it on #15255

Thanks!

vkarpov15 added a commit that referenced this issue Feb 14, 2025
perf(schema): clear childSchemas when overwriting existing path to avoid performance degradations
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. performance
Projects
None yet
2 participants