improve field deletion in collection (#6823)
* added filter to updateMany when deleting field * added test cases * added changelog entry
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
### master
|
### master
|
||||||
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.3.0...master)
|
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.3.0...master)
|
||||||
|
- IMPROVE: Optimized deletion of class field from schema by using an index if available to do an index scan instead of a collection scan. [#6815](https://github.com/parse-community/parse-server/issues/6815). Thanks to [Manuel Trezza](https://github.com/mtrezza).
|
||||||
|
|
||||||
### 4.3.0
|
### 4.3.0
|
||||||
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.2.0...4.3.0)
|
[Full Changelog](https://github.com/parse-community/parse-server/compare/4.2.0...4.3.0)
|
||||||
|
|||||||
@@ -351,6 +351,43 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
|
|||||||
expect(postIndexPlan.executionStats.executionStages.stage).toBe('FETCH');
|
expect(postIndexPlan.executionStats.executionStages.stage).toBe('FETCH');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should delete field without index', async () => {
|
||||||
|
const database = Config.get(Parse.applicationId).database;
|
||||||
|
const obj = new Parse.Object('MyObject');
|
||||||
|
obj.set("test", 1);
|
||||||
|
await obj.save();
|
||||||
|
const schemaBeforeDeletion = await new Parse.Schema('MyObject').get();
|
||||||
|
await database.adapter.deleteFields(
|
||||||
|
"MyObject",
|
||||||
|
schemaBeforeDeletion,
|
||||||
|
["test"]
|
||||||
|
);
|
||||||
|
const schemaAfterDeletion = await new Parse.Schema('MyObject').get();
|
||||||
|
expect(schemaBeforeDeletion.fields.test).toBeDefined();
|
||||||
|
expect(schemaAfterDeletion.fields.test).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should delete field with index', async () => {
|
||||||
|
const database = Config.get(Parse.applicationId).database;
|
||||||
|
const obj = new Parse.Object('MyObject');
|
||||||
|
obj.set("test", 1);
|
||||||
|
await obj.save();
|
||||||
|
const schemaBeforeDeletion = await new Parse.Schema('MyObject').get();
|
||||||
|
await database.adapter.ensureIndex(
|
||||||
|
'MyObject',
|
||||||
|
schemaBeforeDeletion,
|
||||||
|
['test']
|
||||||
|
);
|
||||||
|
await database.adapter.deleteFields(
|
||||||
|
"MyObject",
|
||||||
|
schemaBeforeDeletion,
|
||||||
|
["test"]
|
||||||
|
);
|
||||||
|
const schemaAfterDeletion = await new Parse.Schema('MyObject').get();
|
||||||
|
expect(schemaBeforeDeletion.fields.test).toBeDefined();
|
||||||
|
expect(schemaAfterDeletion.fields.test).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
semver.satisfies(process.env.MONGODB_VERSION, '>=4.0.4') &&
|
semver.satisfies(process.env.MONGODB_VERSION, '>=4.0.4') &&
|
||||||
process.env.MONGODB_TOPOLOGY === 'replicaset' &&
|
process.env.MONGODB_TOPOLOGY === 'replicaset' &&
|
||||||
|
|||||||
@@ -433,6 +433,11 @@ export class MongoStorageAdapter implements StorageAdapter {
|
|||||||
collectionUpdate['$unset'][name] = null;
|
collectionUpdate['$unset'][name] = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const collectionFilter = { $or: [] };
|
||||||
|
mongoFormatNames.forEach(name => {
|
||||||
|
collectionFilter['$or'].push({ [name]: { $exists: true } });
|
||||||
|
});
|
||||||
|
|
||||||
const schemaUpdate = { $unset: {} };
|
const schemaUpdate = { $unset: {} };
|
||||||
fieldNames.forEach((name) => {
|
fieldNames.forEach((name) => {
|
||||||
schemaUpdate['$unset'][name] = null;
|
schemaUpdate['$unset'][name] = null;
|
||||||
@@ -440,7 +445,7 @@ export class MongoStorageAdapter implements StorageAdapter {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return this._adaptiveCollection(className)
|
return this._adaptiveCollection(className)
|
||||||
.then((collection) => collection.updateMany({}, collectionUpdate))
|
.then((collection) => collection.updateMany(collectionFilter, collectionUpdate))
|
||||||
.then(() => this._schemaCollection())
|
.then(() => this._schemaCollection())
|
||||||
.then((schemaCollection) =>
|
.then((schemaCollection) =>
|
||||||
schemaCollection.updateSchema(className, schemaUpdate)
|
schemaCollection.updateSchema(className, schemaUpdate)
|
||||||
|
|||||||
Reference in New Issue
Block a user