Skip to content
49 changes: 48 additions & 1 deletion spec/DefinedSchemas.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ describe('DefinedSchemas', () => {
expect(schema.indexes).toEqual(indexes);
});

it('should delete removed indexes', async () => {
it('should delete unknown indexes when keepUnknownIndexes is not set', async () => {
const server = await reconfigureServer();

let indexes = { complex: { createdAt: 1, updatedAt: 1 } };
Expand All @@ -393,6 +393,53 @@ describe('DefinedSchemas', () => {
cleanUpIndexes(schema);
expect(schema.indexes).toBeUndefined();
});

it('should delete unknown indexes when keepUnknownIndexes is set to false', async () => {
const server = await reconfigureServer();

let indexes = { complex: { createdAt: 1, updatedAt: 1 } };

let schemas = { definitions: [{ className: 'Test', indexes }], keepUnknownIndexes: false };
await new DefinedSchemas(schemas, server.config).execute();

indexes = {};
schemas = { definitions: [{ className: 'Test', indexes }], keepUnknownIndexes: false };
// Change indexes
await new DefinedSchemas(schemas, server.config).execute();
let schema = await new Parse.Schema('Test').get();
cleanUpIndexes(schema);
expect(schema.indexes).toBeUndefined();

// Update
await new DefinedSchemas(schemas, server.config).execute();
schema = await new Parse.Schema('Test').get();
cleanUpIndexes(schema);
expect(schema.indexes).toBeUndefined();
});

it('should not delete unknown indexes when keepUnknownIndexes is set to true', async () => {
const server = await reconfigureServer();

const indexes = { complex: { createdAt: 1, updatedAt: 1 } };

let schemas = { definitions: [{ className: 'Test', indexes }], keepUnknownIndexes: true };
await new DefinedSchemas(schemas, server.config).execute();

schemas = { definitions: [{ className: 'Test', indexes: {} }], keepUnknownIndexes: true };

// Change indexes
await new DefinedSchemas(schemas, server.config).execute();
let schema = await new Parse.Schema('Test').get();
cleanUpIndexes(schema);
expect(schema.indexes).toEqual({ complex: { createdAt: 1, updatedAt: 1 } });

// Update
await new DefinedSchemas(schemas, server.config).execute();
schema = await new Parse.Schema('Test').get();
cleanUpIndexes(schema);
expect(schema.indexes).toEqual(indexes);
});

xit('should keep protected indexes', async () => {
const server = await reconfigureServer();

Expand Down
7 changes: 7 additions & 0 deletions src/Options/Definitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ module.exports.SchemaOptions = {
action: parsers.booleanParser,
default: false,
},
keepUnknownIndexes: {
env: 'PARSE_SERVER_SCHEMA_KEEP_UNKNOWN_INDEXES',
help:
'Keep indexes that are not defined in the schema and are present in the database. Set this to true if you are adding indexes manually so that it wont be dropped when you run schema migration',
action: parsers.booleanParser,
default: false,
},
lockSchemas: {
env: 'PARSE_SERVER_SCHEMA_LOCK_SCHEMAS',
help:
Expand Down
1 change: 1 addition & 0 deletions src/Options/docs.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/Options/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export interface SchemaOptions {
/* Is true if Parse Server will reject any attempts to modify the schema while the server is running.
:DEFAULT: false */
lockSchemas: ?boolean;
/* Keep indexes that are not defined in the schema and are present in the database. Set this to true if you are adding indexes manually so that it wont be dropped when you run schema migration
Copy link
Member

@mtrezza mtrezza Sep 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/* Keep indexes that are not defined in the schema and are present in the database. Set this to true if you are adding indexes manually so that it wont be dropped when you run schema migration
/* (Optional) Keep indexes that are present in the database but not defined in the schema. Set this to `true` if you are adding indexes manually, so that they won't be removed when running schema migration. Default is `false`.

Could you please accept this change and run the definitions script to update the other files?

:DEFAULT: false */
keepUnknownIndexes: ?boolean;
/* Execute a callback before running schema migrations. */
beforeMigration: ?() => void | Promise<void>;
/* Execute a callback after running schema migrations. */
Expand Down
5 changes: 4 additions & 1 deletion src/SchemaMigrations/DefinedSchemas.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,10 @@ export class DefinedSchemas {
Object.keys(cloudSchema.indexes).forEach(indexName => {
if (!this.isProtectedIndex(localSchema.className, indexName)) {
if (!localSchema.indexes || !localSchema.indexes[indexName]) {
newLocalSchema.deleteIndex(indexName);
// If keepUnknownIndex is falsy, then delete all unknown indexes from the db.
if(!this.schemaOptions.keepUnknownIndexes){
newLocalSchema.deleteIndex(indexName);
}
} else if (
!this.paramsAreEquals(localSchema.indexes[indexName], cloudSchema.indexes[indexName])
) {
Expand Down
1 change: 1 addition & 0 deletions src/SchemaMigrations/Migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface SchemaOptions {
deleteExtraFields: ?boolean;
recreateModifiedFields: ?boolean;
lockSchemas: ?boolean;
keepUnknownIndexes: ?boolean;
beforeMigration: ?() => void | Promise<void>;
afterMigration: ?() => void | Promise<void>;
}
Expand Down
Loading