Skip to content

Commit 14032ff

Browse files
committed
perf(schema): clear childSchemas when overwriting existing path to avoid performance degradations
Fix #15253
1 parent 61d16b0 commit 14032ff

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

lib/schema.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,6 +1118,9 @@ Schema.prototype.path = function(path, obj) {
11181118
this.paths[path] = this.interpretAsType(path, obj, this.options);
11191119
const schemaType = this.paths[path];
11201120

1121+
// If overwriting an existing path, make sure to clear the childSchemas
1122+
this.childSchemas = this.childSchemas.filter(childSchema => childSchema.path !== path);
1123+
11211124
if (schemaType.$isSchemaMap) {
11221125
// Maps can have arbitrary keys, so `$*` is internal shorthand for "any key"
11231126
// The '$' is to imply this path should never be stored in MongoDB so we

test/schema.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3889,4 +3889,34 @@ describe('schema', function() {
38893889
assert.throws(() => schema.toJSONSchema(), /unsupported SchemaType to JSON Schema: Mixed/);
38903890
});
38913891
});
3892+
3893+
it('path() clears existing child schemas (gh-15253)', async function() {
3894+
const RecursiveSchema = new mongoose.Schema({
3895+
data: String
3896+
});
3897+
3898+
const s = [RecursiveSchema];
3899+
RecursiveSchema.path('nested', s);
3900+
assert.strictEqual(RecursiveSchema.childSchemas.length, 1);
3901+
RecursiveSchema.path('nested', s);
3902+
assert.strictEqual(RecursiveSchema.childSchemas.length, 1);
3903+
RecursiveSchema.path('nested', s);
3904+
assert.strictEqual(RecursiveSchema.childSchemas.length, 1);
3905+
RecursiveSchema.path('nested', s);
3906+
assert.strictEqual(RecursiveSchema.childSchemas.length, 1);
3907+
3908+
const generateRecursiveDocument = (depth, curr = 0) => {
3909+
return {
3910+
name: `Document of depth ${curr}`,
3911+
nested: depth > 0 ? new Array(3).fill().map(() => generateRecursiveDocument(depth - 1, curr + 1)) : [],
3912+
data: Math.random()
3913+
};
3914+
};
3915+
3916+
const TestModel = db.model('Test', RecursiveSchema);
3917+
const data = generateRecursiveDocument(6);
3918+
const doc = new TestModel(data);
3919+
await doc.save();
3920+
3921+
});
38923922
});

0 commit comments

Comments
 (0)