NestJs - mongoose -动态集合命名

zbdgwd5y  于 2022-11-13  发布在  Go
关注(0)|答案(2)|浏览(219)

我想使用基于当前年份的动态集合名称。
例如:从“产品”到“产品2020”。
使用NESTJS,我必须导入具有特定集合名称的“module.forFeature”。

  1. import { Module } from '@nestjs/common'
  2. import { MongooseModule } from '@nestjs/mongoose'
  3. @Module({
  4. imports: [
  5. MongooseModule.forFeature([
  6. {
  7. name: 'Products',
  8. schema: ProductsSchema
  9. }
  10. ])
  11. ],
  12. controllers: [ProductsController],
  13. providers: [ProductsService]
  14. })

服务时的注入也是如此:

  1. import { Injectable } from '@nestjs/common'
  2. import { InjectModel } from '@nestjs/mongoose'
  3. import { Model } from 'mongoose'
  4. @Injectable()
  5. export class ProductsService {
  6. constructor(
  7. @InjectModel('Products')
  8. private readonly productsModel: Model<Products>
  9. ) {}
  10. }

最后,这是我的模式:

  1. import { Schema } from 'mongoose'
  2. export const ProductsSchema = new Schema(
  3. {
  4. _id: { Type: String, required: true },
  5. code: String
  6. },
  7. {
  8. collection: 'Products'
  9. }
  10. )

是否有某种方法可以实现动态命名?
多谢了!

q5iwbnjs

q5iwbnjs1#

我偶然发现了一个类似的问题,我解决的方法是使用MongooseModule.forFeatureAsync方法。模型和模式声明与nestjs文档中的相同。

  1. @Module({
  2. imports: [
  3. MongooseModule.forFeatureAsync([
  4. {
  5. name: UsersModel.name,
  6. imports: [EnvironmentModule],
  7. inject: [EnvironmentService],
  8. useFactory: (envService: EnvironmentService) => {
  9. const env = envService.getEnv();
  10. const schema = UsersSchema.set(
  11. 'collection',
  12. `${env.countryCode}-users`,
  13. );
  14. return schema;
  15. },
  16. },
  17. ]),
  18. ...
  19. ],
  20. providers: []
  21. ...
展开查看全部
r8xiu3jd

r8xiu3jd2#

我一直在寻找解决这类问题的方法,但我遇到了一堵墙,没有明确的方法来做这件事。
以下(最少)代码示例化服务,每个服务根据country parameter绑定到特定模型。即,ServiceX绑定到数据库X的模型,ServiceY绑定到数据库Y中的相同模型
但这里是我设法做到的。你绝对可以做一个工作来满足你的需要
首先是模型/接口。通常用于不同服务之间

  1. export interface User extends Document {
  2. readonly username: string;
  3. readonly password: string;
  4. }
  5. export const UserSchema = new mongoose.Schema(
  6. {
  7. _id: mongoose.ObjectId,
  8. username: String,
  9. password: String
  10. },
  11. { collection: 'accounts', autoCreate: true }
  12. );

对于不同数据库/集合中的每个模型,服务定义实际上是相同的

  1. @Injectable()
  2. export class XUserService implements OnModuleInit{
  3. constructor(
  4. private userModel: Model<User>,
  5. ) {
  6. }
  7. ////////////////////////////////////////////////////////////////////////////
  8. async onModuleInit(): Promise<any> {
  9. console.log(`inside service dbname=: ${this.userModel.db.name} > ${this.userModel.collection.collectionName}` );
  10. // await new this.userModel({_id: mongoose.Types.ObjectId(), username: 'test', password: 'test', flag: this.c}).save()
  11. }
  12. async insert(){
  13. console.log(`inside service dbname=: ${this.userModel.db.name} > ${this.userModel.collection.collectionName}` );
  14. await new this.userModel({
  15. _id: mongoose.Types.ObjectId(),
  16. username: this.userModel.db.name,
  17. password: '0000'
  18. }).save();
  19. }
  20. async findOne(): Promise<User>{
  21. console.log(`inside service in : ${this.userModel.db.name} > ${this.userModel.collection.collectionName}` );
  22. return this.userModel.findOne()
  23. }
  24. }

对于模块,我创建了一个DynamicModule

  • 导入数据库连接
  • 为每个需求创建一个模型,(对于我的情况,每个数据库中有一个模型)
  • 创建每个Model并将其绑定到一个Service,这样服务的示例化将是正确的
  1. @Module({
  2. })
  3. export class XUserModule{
  4. static register( /*use can pass parameter here*/): DynamicModule{
  5. return{
  6. module: XUserModule,
  7. imports: [
  8. DatabaseModule
  9. ],
  10. controllers: [
  11. XUserController
  12. ],
  13. providers: [
  14. // Create Models here, #1 and #2 in two different database
  15. {
  16. provide: 'dz-'+'UserModel',
  17. useFactory: (connection: Connection)=> {
  18. return connection.model('User', UserSchema )
  19. },
  20. inject: [ dbname.shooffood('dz')+'Connection' ]
  21. },{
  22. provide: 'ca-'+'UserModel',
  23. useFactory: (connection: Connection)=> {
  24. return connection.model('User', UserSchema )
  25. },
  26. inject: [ dbname.shooffood('ca')+'Connection' ]
  27. },
  28. // Create Providers/Services for each Model and Inject the Model to the Service by `TokenString`
  29. {
  30. provide: 'dz' + XUserService.name,
  31. useFactory: (m: any)=> {
  32. console.log(m);
  33. return new XUserService(m);
  34. },
  35. inject: [ 'dz-'+'UserModel' ]
  36. },{
  37. provide: 'ca' + XUserService.name,
  38. useFactory: (m: any)=> {
  39. console.log(m);
  40. return new XUserService(m);
  41. },
  42. inject: [ 'ca-'+'UserModel' ]
  43. }
  44. ],
  45. // Export your service with the same `provide` name for later usage.
  46. exports: [
  47. 'dz' + XUserService.name,
  48. 'ca' + XUserService.name
  49. ]
  50. }
  51. }
  52. }

仅供参考,数据库模块看起来像常数dbname是连接名称,uri是连接字符串。

  1. const databaseProviders = [
  2. {
  3. provide: dbname.admin+'Connection',
  4. useFactory: (): Promise<typeof mongoose> => mongoose.createConnection(uri.admin),
  5. },{
  6. provide: dbname.system+'Connection',
  7. useFactory: (): Promise<typeof mongoose> => mongoose.createConnection(uri.system),
  8. },{
  9. provide: dbname.shooffood('dz')+'Connection',
  10. useFactory: (): Promise<typeof mongoose> => mongoose.createConnection(uri.dzfood),
  11. },{
  12. provide: dbname.shooffood('ca')+'Connection',
  13. useFactory: (): Promise<typeof mongoose> => mongoose.createConnection(uri.cafood),
  14. }
  15. ];
  16. @Module({
  17. providers: [
  18. ...databaseProviders
  19. ],
  20. exports: [
  21. dbname.admin+'Connection',
  22. dbname.system+'Connection',
  23. dbname.shooffood('dz')+'Connection',
  24. dbname.shooffood('ca')+'Connection'
  25. ]
  26. })
  27. export class DatabaseModule {}

至于控制器,只有一个通过请求参数:country处理每个服务。但首先我必须列出所有可能的模型和服务,以包括在应用程序中。

  1. @Controller(':country')
  2. export class XUserController {
  3. private byCountryServices = new Map();
  4. constructor(
  5. // Inject all required services by `tokenString`
  6. @Inject('dz' + XUserService.name) private dzUserService: XUserService,
  7. @Inject('ca' + XUserService.name) private caUserService: XUserService,
  8. ) {
  9. // Add to `<key, value>` Map for easy by param access
  10. this.byCountryServices.set('dz', this.dzUserService );
  11. this.byCountryServices.set('ca', this.caUserService );
  12. }
  13. @Get('post')
  14. async post(
  15. @Param('country') c: string
  16. ): Promise<string>{
  17. await this.byCountryServices.get(c).insert()
  18. return 'inserted in ' + c;
  19. }
  20. @Get('get')
  21. async get(
  22. @Param('country') c: string
  23. ): Promise<string>{
  24. console.log('param: ' + c)
  25. return await this.byCountryServices.get(c).findOne()
  26. }
  27. }

最后,使用XUserModule.register()在AppModule中导入该模块

展开查看全部

相关问题