You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中Mongoose Schema读取process.env返回undefined如何解决

问题根因
  • @Prop() 装饰器内的代码会在文件导入、类加载阶段立即执行,这个时机早于ConfigModule.forRoot()解析.env文件并将配置挂载到process.env的时间,直接写process.env.NAME自然拿到undefined。
  • 现有MongooseModule.forFeatureAsync写法没有注入配置依赖,也没有延迟Schema属性配置的初始化逻辑,直接返回了提前加载完成、默认值已经固化为undefined的Schema实例。
  • PetsModule中重复导入ConfigModule属于冗余代码,AppModule中已经开启isGlobal: true,配置服务全局可用。
修正步骤
  1. 先调整Schema文件,移除@Prop()中静态写死的环境变量读取逻辑:
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { Document } from 'mongoose';

export type PetDocument = Pet & Document;

@Schema()
export class Pet {
  @Prop()
  name: string;

  @Prop()
  age: number;

  @Prop()
  breed: string;
}

export const PetSchema = SchemaFactory.createForClass(Pet);
  1. 修改PetsModule的异步注册逻辑,注入ConfigService,在工厂函数中(此时配置模块已经完成初始化)动态给Schema字段设置默认值:
import { Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';
import { PetsService } from './pets.service';
import { Pet, PetSchema } from './schema/pets.schema';

@Module({
  imports: [
    MongooseModule.forFeatureAsync([
      {
        name: Pet.name,
        useFactory: (configService: ConfigService) => {
          const defaultPetName = configService.get<string>('NAME');
          PetSchema.path('name').default(defaultPetName);
          return PetSchema;
        },
        inject: [ConfigService],
      },
    ]),
  ],
  providers: [PetsService],
})
export class PetsModule {}
  1. (规范建议)调整AppModule中数据库连接的配置写法,同样通过注入ConfigService读取配置,避免偶发的时序问题:
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MongooseModule } from '@nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PetsModule } from './pets/pets.module';

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
    MongooseModule.forRootAsync({
      useFactory: (configService: ConfigService) => ({
        uri: configService.get<string>('DB_URI'),
      }),
      inject: [ConfigService],
    }),
    PetsModule,
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
注意事项
  • 禁止在类装饰器、属性装饰器的参数位置直接读取process.env或调用需要依赖其他模块初始化的逻辑,装饰器执行时机远早于NestJS依赖注入容器的初始化流程,必然会出现依赖未就绪的问题。
  • 所有依赖配置、其他服务的动态初始化逻辑,都要放到对应模块的异步工厂useFactory中执行,并且通过inject数组声明依赖,NestJS会等待所有依赖初始化完成后再执行工厂逻辑,保证能拿到正确的值。

内容的提问来源于stack exchange,提问作者Otávio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 01:24:23