diff --git a/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts b/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts index fca460bfd..abd6f7c20 100644 --- a/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts +++ b/modules/database/src/adapters/mongoose-adapter/MongooseSchema.ts @@ -50,12 +50,8 @@ export class MongooseSchema extends SchemaAdapter> { } const mongooseSchema = new Schema(cloneDeep(schema.fields as Indexable), { ...cloneDeep(schema.modelOptions), - ...(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 2959be4f7..73bfd5910 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 { @@ -289,6 +290,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'); @@ -455,6 +493,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]; }