diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js
index b026fc0961..7d0d220cff 100644
--- a/spec/MongoStorageAdapter.spec.js
+++ b/spec/MongoStorageAdapter.spec.js
@@ -649,4 +649,179 @@ describe_only_db('mongo')('MongoStorageAdapter', () => {
});
});
}
+
+ describe('index creation options', () => {
+ beforeEach(async () => {
+ await new MongoStorageAdapter({ uri: databaseURI }).deleteAllClasses();
+ });
+
+ async function getIndexes(collectionName) {
+ const adapter = Config.get(Parse.applicationId).database.adapter;
+ const collections = await adapter.database.listCollections({ name: collectionName }).toArray();
+ if (collections.length === 0) {
+ return [];
+ }
+ return await adapter.database.collection(collectionName).indexes();
+ }
+
+ it('should skip username index when createIndexUserUsername is false', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserUsername: false },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === 'username_1')).toBeUndefined();
+ });
+
+ it('should create username index when createIndexUserUsername is true', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserUsername: true },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === 'username_1')).toBeDefined();
+ });
+
+ it('should skip case-insensitive username index when createIndexUserUsernameCaseInsensitive is false', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserUsernameCaseInsensitive: false },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === 'case_insensitive_username')).toBeUndefined();
+ });
+
+ it('should create case-insensitive username index when createIndexUserUsernameCaseInsensitive is true', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserUsernameCaseInsensitive: true },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === 'case_insensitive_username')).toBeDefined();
+ });
+
+ it('should skip email index when createIndexUserEmail is false', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserEmail: false },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === 'email_1')).toBeUndefined();
+ });
+
+ it('should create email index when createIndexUserEmail is true', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserEmail: true },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === 'email_1')).toBeDefined();
+ });
+
+ it('should skip case-insensitive email index when createIndexUserEmailCaseInsensitive is false', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserEmailCaseInsensitive: false },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === 'case_insensitive_email')).toBeUndefined();
+ });
+
+ it('should create case-insensitive email index when createIndexUserEmailCaseInsensitive is true', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserEmailCaseInsensitive: true },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === 'case_insensitive_email')).toBeDefined();
+ });
+
+ it('should skip email verify token index when createIndexUserEmailVerifyToken is false', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserEmailVerifyToken: false },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === '_email_verify_token' || idx.name === '_email_verify_token_1')).toBeUndefined();
+ });
+
+ it('should create email verify token index when createIndexUserEmailVerifyToken is true', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserEmailVerifyToken: true },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === '_email_verify_token' || idx.name === '_email_verify_token_1')).toBeDefined();
+ });
+
+ it('should skip password reset token index when createIndexUserPasswordResetToken is false', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserPasswordResetToken: false },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === '_perishable_token' || idx.name === '_perishable_token_1')).toBeUndefined();
+ });
+
+ it('should create password reset token index when createIndexUserPasswordResetToken is true', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexUserPasswordResetToken: true },
+ });
+ const indexes = await getIndexes('_User');
+ expect(indexes.find(idx => idx.name === '_perishable_token' || idx.name === '_perishable_token_1')).toBeDefined();
+ });
+
+ it('should skip role name index when createIndexRoleName is false', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexRoleName: false },
+ });
+ const indexes = await getIndexes('_Role');
+ expect(indexes.find(idx => idx.name === 'name_1')).toBeUndefined();
+ });
+
+ it('should create role name index when createIndexRoleName is true', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: { createIndexRoleName: true },
+ });
+ const indexes = await getIndexes('_Role');
+ expect(indexes.find(idx => idx.name === 'name_1')).toBeDefined();
+ });
+
+ it('should create all indexes by default when options are undefined', async () => {
+ await reconfigureServer({
+ databaseAdapter: undefined,
+ databaseURI,
+ databaseOptions: {},
+ });
+
+ const userIndexes = await getIndexes('_User');
+ const roleIndexes = await getIndexes('_Role');
+
+ // Verify all indexes are created with default behavior (backward compatibility)
+ expect(userIndexes.find(idx => idx.name === 'username_1')).toBeDefined();
+ expect(userIndexes.find(idx => idx.name === 'case_insensitive_username')).toBeDefined();
+ expect(userIndexes.find(idx => idx.name === 'email_1')).toBeDefined();
+ expect(userIndexes.find(idx => idx.name === 'case_insensitive_email')).toBeDefined();
+ expect(userIndexes.find(idx => idx.name === '_email_verify_token' || idx.name === '_email_verify_token_1')).toBeDefined();
+ expect(userIndexes.find(idx => idx.name === '_perishable_token' || idx.name === '_perishable_token_1')).toBeDefined();
+ expect(roleIndexes.find(idx => idx.name === 'name_1')).toBeDefined();
+ });
+ });
});
diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js
index ad5a69ea70..39b335d52e 100644
--- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js
+++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js
@@ -154,8 +154,22 @@ export class MongoStorageAdapter implements StorageAdapter {
this.enableSchemaHooks = !!mongoOptions.enableSchemaHooks;
this.schemaCacheTtl = mongoOptions.schemaCacheTtl;
this.disableIndexFieldValidation = !!mongoOptions.disableIndexFieldValidation;
- for (const key of ['enableSchemaHooks', 'schemaCacheTtl', 'maxTimeMS', 'disableIndexFieldValidation']) {
- delete mongoOptions[key];
+ // Remove Parse Server-specific options that should not be passed to MongoDB client
+ // Note: We only delete from this._mongoOptions, not from the original mongoOptions object,
+ // because other components (like DatabaseController) need access to these options
+ for (const key of [
+ 'enableSchemaHooks',
+ 'schemaCacheTtl',
+ 'maxTimeMS',
+ 'disableIndexFieldValidation',
+ 'createIndexUserUsername',
+ 'createIndexUserUsernameCaseInsensitive',
+ 'createIndexUserEmail',
+ 'createIndexUserEmailCaseInsensitive',
+ 'createIndexUserEmailVerifyToken',
+ 'createIndexUserPasswordResetToken',
+ 'createIndexRoleName',
+ ]) {
delete this._mongoOptions[key];
}
}
diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js
index e3b5cc210a..f08bface5a 100644
--- a/src/Controllers/DatabaseController.js
+++ b/src/Controllers/DatabaseController.js
@@ -1738,50 +1738,66 @@ class DatabaseController {
await this.loadSchema().then(schema => schema.enforceClassExists('_Role'));
await this.loadSchema().then(schema => schema.enforceClassExists('_Idempotency'));
- await this.adapter.ensureUniqueness('_User', requiredUserFields, ['username']).catch(error => {
- logger.warn('Unable to ensure uniqueness for usernames: ', error);
- throw error;
- });
+ const databaseOptions = this.options.databaseOptions || {};
+
+ if (databaseOptions.createIndexUserUsername !== false) {
+ await this.adapter.ensureUniqueness('_User', requiredUserFields, ['username']).catch(error => {
+ logger.warn('Unable to ensure uniqueness for usernames: ', error);
+ throw error;
+ });
+ }
if (!this.options.enableCollationCaseComparison) {
+ if (databaseOptions.createIndexUserUsernameCaseInsensitive !== false) {
+ await this.adapter
+ .ensureIndex('_User', requiredUserFields, ['username'], 'case_insensitive_username', true)
+ .catch(error => {
+ logger.warn('Unable to create case insensitive username index: ', error);
+ throw error;
+ });
+ }
+
+ if (databaseOptions.createIndexUserEmailCaseInsensitive !== false) {
+ await this.adapter
+ .ensureIndex('_User', requiredUserFields, ['email'], 'case_insensitive_email', true)
+ .catch(error => {
+ logger.warn('Unable to create case insensitive email index: ', error);
+ throw error;
+ });
+ }
+ }
+
+ if (databaseOptions.createIndexUserEmail !== false) {
+ await this.adapter.ensureUniqueness('_User', requiredUserFields, ['email']).catch(error => {
+ logger.warn('Unable to ensure uniqueness for user email addresses: ', error);
+ throw error;
+ });
+ }
+
+ if (databaseOptions.createIndexUserEmailVerifyToken !== false) {
await this.adapter
- .ensureIndex('_User', requiredUserFields, ['username'], 'case_insensitive_username', true)
+ .ensureIndex('_User', requiredUserFields, ['_email_verify_token'], '_email_verify_token', false)
.catch(error => {
- logger.warn('Unable to create case insensitive username index: ', error);
+ logger.warn('Unable to create index for email verification token: ', error);
throw error;
});
+ }
+ if (databaseOptions.createIndexUserPasswordResetToken !== false) {
await this.adapter
- .ensureIndex('_User', requiredUserFields, ['email'], 'case_insensitive_email', true)
+ .ensureIndex('_User', requiredUserFields, ['_perishable_token'], '_perishable_token', false)
.catch(error => {
- logger.warn('Unable to create case insensitive email index: ', error);
+ logger.warn('Unable to create index for password reset token: ', error);
throw error;
});
}
- await this.adapter.ensureUniqueness('_User', requiredUserFields, ['email']).catch(error => {
- logger.warn('Unable to ensure uniqueness for user email addresses: ', error);
- throw error;
- });
-
- await this.adapter
- .ensureIndex('_User', requiredUserFields, ['_email_verify_token'], '_email_verify_token', false)
- .catch(error => {
- logger.warn('Unable to create index for email verification token: ', error);
- throw error;
- });
-
- await this.adapter
- .ensureIndex('_User', requiredUserFields, ['_perishable_token'], '_perishable_token', false)
- .catch(error => {
- logger.warn('Unable to create index for password reset token: ', error);
+ if (databaseOptions.createIndexRoleName !== false) {
+ await this.adapter.ensureUniqueness('_Role', requiredRoleFields, ['name']).catch(error => {
+ logger.warn('Unable to ensure uniqueness for role name: ', error);
throw error;
});
-
- await this.adapter.ensureUniqueness('_Role', requiredRoleFields, ['name']).catch(error => {
- logger.warn('Unable to ensure uniqueness for role name: ', error);
- throw error;
- });
+ }
await this.adapter
.ensureUniqueness('_Idempotency', requiredIdempotencyFields, ['reqId'])
diff --git a/src/Options/Definitions.js b/src/Options/Definitions.js
index 205c35fa77..d2f1e6eef1 100644
--- a/src/Options/Definitions.js
+++ b/src/Options/Definitions.js
@@ -1101,6 +1101,55 @@ module.exports.DatabaseOptions = {
'The MongoDB driver option to specify the amount of time, in milliseconds, to wait to establish a single TCP socket connection to the server before raising an error. Specifying 0 disables the connection timeout.',
action: parsers.numberParser('connectTimeoutMS'),
},
+ createIndexRoleName: {
+ env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_ROLE_NAME',
+ help:
+ 'Set to `true` to automatically create a unique index on the name field of the _Role collection on server start. Set to `false` to skip index creation. Default is `true`.
\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
+ action: parsers.booleanParser,
+ default: true,
+ },
+ createIndexUserEmail: {
+ env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_USER_EMAIL',
+ help:
+ 'Set to `true` to automatically create indexes on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
+ action: parsers.booleanParser,
+ default: true,
+ },
+ createIndexUserEmailCaseInsensitive: {
+ env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_USER_EMAIL_CASE_INSENSITIVE',
+ help:
+ 'Set to `true` to automatically create a case-insensitive index on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
+ action: parsers.booleanParser,
+ default: true,
+ },
+ createIndexUserEmailVerifyToken: {
+ env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_USER_EMAIL_VERIFY_TOKEN',
+ help:
+ 'Set to `true` to automatically create an index on the _email_verify_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
+ action: parsers.booleanParser,
+ default: true,
+ },
+ createIndexUserPasswordResetToken: {
+ env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_USER_PASSWORD_RESET_TOKEN',
+ help:
+ 'Set to `true` to automatically create an index on the _perishable_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
+ action: parsers.booleanParser,
+ default: true,
+ },
+ createIndexUserUsername: {
+ env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_USER_USERNAME',
+ help:
+ 'Set to `true` to automatically create indexes on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
+ action: parsers.booleanParser,
+ default: true,
+ },
+ createIndexUserUsernameCaseInsensitive: {
+ env: 'PARSE_SERVER_DATABASE_CREATE_INDEX_USER_USERNAME_CASE_INSENSITIVE',
+ help:
+ 'Set to `true` to automatically create a case-insensitive index on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
\u26A0\uFE0F When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.',
+ action: parsers.booleanParser,
+ default: true,
+ },
disableIndexFieldValidation: {
env: 'PARSE_SERVER_DATABASE_DISABLE_INDEX_FIELD_VALIDATION',
help:
diff --git a/src/Options/docs.js b/src/Options/docs.js
index dde5942500..9e650b1038 100644
--- a/src/Options/docs.js
+++ b/src/Options/docs.js
@@ -243,6 +243,13 @@
* @property {Boolean} autoSelectFamily The MongoDB driver option to set whether the socket attempts to connect to IPv6 and IPv4 addresses until a connection is established. If available, the driver will select the first IPv6 address.
* @property {Number} autoSelectFamilyAttemptTimeout The MongoDB driver option to specify the amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the autoSelectFamily option. If set to a positive integer less than 10, the value 10 is used instead.
* @property {Number} connectTimeoutMS The MongoDB driver option to specify the amount of time, in milliseconds, to wait to establish a single TCP socket connection to the server before raising an error. Specifying 0 disables the connection timeout.
+ * @property {Boolean} createIndexRoleName Set to `true` to automatically create a unique index on the name field of the _Role collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ * @property {Boolean} createIndexUserEmail Set to `true` to automatically create indexes on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ * @property {Boolean} createIndexUserEmailCaseInsensitive Set to `true` to automatically create a case-insensitive index on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ * @property {Boolean} createIndexUserEmailVerifyToken Set to `true` to automatically create an index on the _email_verify_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ * @property {Boolean} createIndexUserPasswordResetToken Set to `true` to automatically create an index on the _perishable_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ * @property {Boolean} createIndexUserUsername Set to `true` to automatically create indexes on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ * @property {Boolean} createIndexUserUsernameCaseInsensitive Set to `true` to automatically create a case-insensitive index on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
* @property {Boolean} disableIndexFieldValidation Set to `true` to disable validation of index fields. When disabled, indexes can be created even if the fields do not exist in the schema. This can be useful when creating indexes on fields that will be added later.
* @property {Boolean} enableSchemaHooks Enables database real-time hooks to update single schema cache. Set to `true` if using multiple Parse Servers instances connected to the same database. Failing to do so will cause a schema change to not propagate to all instances and re-syncing will only happen when the instances restart. To use this feature with MongoDB, a replica set cluster with [change stream](https://docs.mongodb.com/manual/changeStreams/#availability) support is required.
* @property {Number} maxPoolSize The MongoDB driver option to set the maximum number of opened, cached, ready-to-use database connections maintained by the driver.
diff --git a/src/Options/index.js b/src/Options/index.js
index ff8287b86b..42da7b2237 100644
--- a/src/Options/index.js
+++ b/src/Options/index.js
@@ -632,6 +632,27 @@ export interface DatabaseOptions {
autoSelectFamily: ?boolean;
/* The MongoDB driver option to specify the amount of time in milliseconds to wait for a connection attempt to finish before trying the next address when using the autoSelectFamily option. If set to a positive integer less than 10, the value 10 is used instead. */
autoSelectFamilyAttemptTimeout: ?number;
+ /* Set to `true` to automatically create indexes on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ :DEFAULT: true */
+ createIndexUserEmail: ?boolean;
+ /* Set to `true` to automatically create a case-insensitive index on the email field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ :DEFAULT: true */
+ createIndexUserEmailCaseInsensitive: ?boolean;
+ /* Set to `true` to automatically create an index on the _email_verify_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ :DEFAULT: true */
+ createIndexUserEmailVerifyToken: ?boolean;
+ /* Set to `true` to automatically create an index on the _perishable_token field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ :DEFAULT: true */
+ createIndexUserPasswordResetToken: ?boolean;
+ /* Set to `true` to automatically create indexes on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ :DEFAULT: true */
+ createIndexUserUsername: ?boolean;
+ /* Set to `true` to automatically create a case-insensitive index on the username field of the _User collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ :DEFAULT: true */
+ createIndexUserUsernameCaseInsensitive: ?boolean;
+ /* Set to `true` to automatically create a unique index on the name field of the _Role collection on server start. Set to `false` to skip index creation. Default is `true`.
⚠️ When setting this option to `false` to manually create the index, keep in mind that the otherwise automatically created index may change in the future to be optimized for the internal usage by Parse Server.
+ :DEFAULT: true */
+ createIndexRoleName: ?boolean;
/* Set to `true` to disable validation of index fields. When disabled, indexes can be created even if the fields do not exist in the schema. This can be useful when creating indexes on fields that will be added later. */
disableIndexFieldValidation: ?boolean;
}