Nestjs: Не удается асинхронно подключить mongo

#nestjs #nestjs-config

Вопрос:

Я не могу асинхронно подключиться к mongodb. Пожалуйста, дайте мне знать, что я делаю не так.

Файл MongoConfig:

 import { MongooseModuleOptions } from '@nestjs/mongoose';

export default (): { mongoConfig: MongooseModuleOptions } => ({
  mongoConfig: {
    uri: process.env.DB_URI,
    connectionName: 'learn-nest',
    useCreateIndex: true,
    useUnifiedTopology: true,
    useFindAndModify: false,
    useNewUrlParser: true,
  },
});

 

Вот код, написанный внутри модуля приложения

 import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MongooseModule } from '@nestjs/mongoose';
import { ConfigModule, ConfigService } from '@nestjs/config';

@Module({
  imports: [
    ConfigModule.forRoot({
      envFilePath: ['.env'],
      isGlobal: true,
      cache: true,
    }),
    MongooseModule.forRootAsync({
      useFactory: (configService: ConfigService): any => {
        configService.get('mongoConfig');
      },
      inject: [ConfigService],
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

 

Это ошибка, которую он выдает:

«Невозможно уничтожить свойство ‘retryAttempts’ из ‘mongooseModuleOptions’, поскольку оно не определено»

Я не понимаю, почему возникает эта ошибка, потому что «retryAttempts» является необязательным свойством в интерфейсе MongooseModuleOptions.

Мангустомодулентерфейс

 export interface MongooseModuleOptions extends ConnectOptions, Record<string, any> {
    uri?: string;
    retryAttempts?: number;
    retryDelay?: number;
    connectionName?: string;
    connectionFactory?: (connection: any, name: string) => any;
}
 

Ответ №1:

Если вы собираетесь использовать асинхронную конфигурацию MongoDB, перейдите к отдельному классу конфигурации. Я объясню, как:

Создайте новую службу для разрешения конфигурации MongoDB.

mongodb.config.service.ts

 import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import {
  MongooseModuleOptions,
  MongooseOptionsFactory,
} from '@nestjs/mongoose';

@Injectable()
export class MongodbConfigService implements MongooseOptionsFactory {

  constructor(private readonly configService: ConfigService) {}

  //You can retrun promise as well
  public createMongooseOptions(): MongooseModuleOptions {
    return {
      //MONGODB_URL is in .env file
      //MONGO_REPL_SET is in .env file
      //MONGO_AUTH_SOURCE is in .env file
      uri: this.configService.get<string>('MONGODB_URL'),
      useNewUrlParser: true,
      useFindAndModify: false,
      useCreateIndex: true,
      useUnifiedTopology: true,
      replicaSet: this.configService.get<string>('MONGO_REPL_SET'),
      authSource:  this.configService.get<string>('MONGO_AUTH_SOURCE'),
    };
  }
}
 

Импорт модуля мангуста :

 //...
MongooseModule.forRootAsync({
      imports: [ConfigModule],
      useClass: MongodbConfigService,
    }),
//...
 

Если вы хотите настроить MongoDB в качестве пространства имен конфигурации :

Создайте файл для хранения конфигурации: mongodb.config.ts

 import { registerAs } from '@nestjs/config';

// @returns MongooseModuleOptions
export default registerAs('mongo_db', () => ({
      //MONGODB_URL is in .env file
      //MONGO_REPL_SET is in .env file
      //MONGO_AUTH_SOURCE is in .env file
      uri: process.env.MONGODB_URL,
      useNewUrlParser: true,
      useFindAndModify: false,
      useCreateIndex: true,
      useUnifiedTopology: true,
      replicaSet: process.env.MONGO_REPL_SET,
      authSource: process.env.MONGO_AUTH_SOURCE,
}));
 

Теперь в модуле конфигурации импорт:

 import mongoDbConfig from '<path>/mongodb.config';
//...
ConfigModule.forRoot({
      envFilePath: ['.env'],
      isGlobal: true,
      cache: true,
      load:[mongoDbConfig]
    }),
//...
 

Импорт модуля мангуста :

 //...
MongooseModule.forRootAsync({
    useFactory:(configService:ConfigService)=>{
       return this.configService.get<MongooseModuleOptions>('mongo_db')
       },
    inject: [ConfigService],
    }),
//...
 

Оба подхода должны сработать.

Кстати: Набор реплик и источник аутентификации были скопированы из моей конфигурации. игнорируйте его, если у вас нет настройки реплики.

Комментарии:

1. Большое вам спасибо за это замечательное объяснение. Теперь мне ясно, как это работает.

Ответ №2:

Ваш useFactory ничего не возвращает, так что у вас нет вариантов для MongooseModule использования. Это было бы похоже на то, чтобы сделать что-то подобное

 function getConfig(configService) {
  config.get('CONFIG_KEY');
}

const config = getConfig(configServce);
console.log(config) // undefined
 

Заводская функция не возвращает значение, поэтому она не определена. Вы можете добавить return configServicce.get('mongoConfig') , и это должно работать так, как ожидалось. Или вы можете заставить функцию анонимной стрелки возвращать объект с помощью () => ({}) . () Окружение {} очень важно для возврата встроенного объекта, в противном случае JS считает, что это тело функции.

Комментарии:

1. Спасибо тебе за внимание, Джей. Я попытался вернуть mongoConfig, но он все равно выдает ту же ошибку.