diff --git a/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts b/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts index 70e20e0b5..c6a089cba 100644 --- a/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts +++ b/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts @@ -65,12 +65,8 @@ export class MongooseSchema extends SchemaAdapter> { this.schemaLevelReadPreference = schemaRp; const mongooseSchema = new Schema(cloneDeep(schema.fields as Indexable), { ...mo, - ...(isView - ? { - autoCreate: false, - autoIndex: false, - } - : {}), + autoCreate: false, + autoIndex: false, }); this.model = mongoose.model(cloneDeep(schema.name), mongooseSchema); } diff --git a/modules/database/src/adapters/mongoose-adapter/index.ts b/modules/database/src/adapters/mongoose-adapter/index.ts index ac5ee694d..7d5362f57 100644 --- a/modules/database/src/adapters/mongoose-adapter/index.ts +++ b/modules/database/src/adapters/mongoose-adapter/index.ts @@ -1,4 +1,5 @@ import { ConnectOptions, Mongoose, Types } from 'mongoose'; +import type { IndexSpecification } from 'mongodb'; import { MongooseSchema } from './MongooseSchema.js'; import { schemaConverter } from './SchemaConverter.js'; import { @@ -640,6 +641,43 @@ export class MongooseAdapter extends DatabaseAdapter { return 'Indexes created!'; } + private async createMongooseFieldIndexes(schemaName: string): Promise { + const model = this.models[schemaName]; + if (!model) throw new GrpcError(status.NOT_FOUND, 'Requested schema not found'); + if (model.isView) return; + + const declaredIndexes = model.model.schema.indexes(); + if (!declaredIndexes.length) return; + + const collection = this.mongoose.model(schemaName).collection; + for (const [keys, rawOptions] of declaredIndexes) { + const indexKeys = keys as IndexSpecification; + if (this.isDefaultIdIndex(indexKeys)) continue; + + const options = this.sanitizeMongooseIndexOptions( + rawOptions as Record, + ); + await collection.createIndex(indexKeys, options).catch((e: Error) => { + throw new GrpcError(status.INTERNAL, e.message); + }); + } + } + + private isDefaultIdIndex(keys: IndexSpecification): boolean { + if (!keys || typeof keys !== 'object' || Array.isArray(keys)) return false; + const entries = Object.entries(keys as Record); + return entries.length === 1 && entries[0][0] === '_id' && entries[0][1] === 1; + } + + private sanitizeMongooseIndexOptions( + options?: Record, + ): Record | undefined { + if (!options) return undefined; + const sanitized = { ...options }; + delete sanitized._autoIndex; + return Object.keys(sanitized).length > 0 ? sanitized : undefined; + } + async getIndexes(schemaName: string): Promise { if (!this.models[schemaName]) throw new GrpcError(status.NOT_FOUND, 'Requested schema not found'); @@ -806,6 +844,9 @@ export class MongooseAdapter extends DatabaseAdapter { if (indexes && !isInstanceSync) { await this.createIndexes(schema.name, indexes, schema.ownerModule); } + if (!isInstanceSync) { + await this.createMongooseFieldIndexes(schema.name); + } return this.models[schema.name]; }