Skip to content

Commit

Permalink
Merge pull request #15256 from Automattic/vkarpov15/gh-15253
Browse files Browse the repository at this point in the history
perf(schema): clear childSchemas when overwriting existing path to avoid performance degradations
  • Loading branch information
vkarpov15 authored Feb 14, 2025
2 parents f1c6ad2 + 14032ff commit d48bc5f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -1118,6 +1118,9 @@ Schema.prototype.path = function(path, obj) {
this.paths[path] = this.interpretAsType(path, obj, this.options);
const schemaType = this.paths[path];

// If overwriting an existing path, make sure to clear the childSchemas
this.childSchemas = this.childSchemas.filter(childSchema => childSchema.path !== path);

if (schemaType.$isSchemaMap) {
// Maps can have arbitrary keys, so `$*` is internal shorthand for "any key"
// The '$' is to imply this path should never be stored in MongoDB so we
Expand Down
30 changes: 30 additions & 0 deletions test/schema.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3889,4 +3889,34 @@ describe('schema', function() {
assert.throws(() => schema.toJSONSchema(), /unsupported SchemaType to JSON Schema: Mixed/);
});
});

it('path() clears existing child schemas (gh-15253)', async function() {
const RecursiveSchema = new mongoose.Schema({
data: String
});

const s = [RecursiveSchema];
RecursiveSchema.path('nested', s);
assert.strictEqual(RecursiveSchema.childSchemas.length, 1);
RecursiveSchema.path('nested', s);
assert.strictEqual(RecursiveSchema.childSchemas.length, 1);
RecursiveSchema.path('nested', s);
assert.strictEqual(RecursiveSchema.childSchemas.length, 1);
RecursiveSchema.path('nested', s);
assert.strictEqual(RecursiveSchema.childSchemas.length, 1);

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: Math.random()
};
};

const TestModel = db.model('Test', RecursiveSchema);
const data = generateRecursiveDocument(6);
const doc = new TestModel(data);
await doc.save();

});
});

0 comments on commit d48bc5f

Please sign in to comment.