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

NestJS实现动态模型:根据年份参数匹配对应集合

Solution for Dynamic Year-Prefixed Collections in NestJS

If you’re working with MongoDB (the most common use case for "collections" in NestJS), here’s a straightforward way to implement dynamic models based on a year parameter:

1. Define a Reusable Base Schema

First, create a schema that matches the structure of documents across all your year-prefixed collections (e.g., 2020-foo, 2021-foo):

// foo.schema.ts
import { Schema } from 'mongoose';

export const FooSchema = new Schema({
  // Add your document fields here
  name: String,
  value: Number,
  createdAt: { type: Date, default: Date.now },
});

// Optional: Define a type for type safety
export interface FooDocument extends Document {
  name: string;
  value: number;
  createdAt: Date;
}

2. Build a Dynamic Model Service

Create a service that generates the correct Mongoose model on demand using the year parameter. This leverages NestJS’s database connection to avoid duplicate model registrations:

// dynamic-foo.service.ts
import { Injectable, Inject } from '@nestjs/common';
import { Connection, Model } from 'mongoose';
import { FooSchema, FooDocument } from './foo.schema';

@Injectable()
export class DynamicFooService {
  constructor(@Inject('DATABASE_CONNECTION') private readonly connection: Connection) {}

  getFooModel(year: number): Model<FooDocument> {
    const collectionName = `${year}-foo`;
    
    // Reuse existing model if it's already registered
    if (this.connection.models[collectionName]) {
      return this.connection.models[collectionName] as Model<FooDocument>;
    }
    
    // Create and return a new model for the target collection
    return this.connection.model<FooDocument>(collectionName, FooSchema);
  }
}

3. Register the Database Connection

In your root module (e.g., AppModule), set up the Mongoose connection and make the dynamic service available:

// app.module.ts
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { DynamicFooService } from './dynamic-foo.service';
import { FooController } from './foo.controller';

@Module({
  imports: [
    MongooseModule.forRoot('mongodb://localhost:27017/your-db-name'),
  ],
  providers: [DynamicFooService],
  controllers: [FooController],
})
export class AppModule {}

4. Use the Dynamic Model in a Controller

Inject the service into your controller, validate the year parameter, and fetch the correct model to run database operations:

// foo.controller.ts
import { Controller, Get, Param, BadRequestException } from '@nestjs/common';
import { DynamicFooService } from './dynamic-foo.service';

@Controller('foo')
export class FooController {
  constructor(private readonly dynamicFooService: DynamicFooService) {}

  @Get(':year')
  async getFooData(@Param('year') yearStr: string) {
    const year = parseInt(yearStr, 10);
    
    if (isNaN(year) || year < 2000 || year > new Date().getFullYear()) {
      throw new BadRequestException('Invalid year parameter');
    }

    const fooModel = this.dynamicFooService.getFooModel(year);
    return fooModel.find().exec();
  }
}

Key Tips

  • Model Caching: The service checks for existing models to avoid Mongoose errors from redefining the same model multiple times.
  • Validation: Always validate the year input to prevent invalid collection names or unexpected behavior.
  • TypeORM Alternative: If using SQL with TypeORM, replace the model logic with EntityManager.getRepository() using the dynamic table name (e.g., ${year}_foo).

内容的提问来源于stack exchange,提问作者mohamed ouf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 22:25:22