我想使用基于当前年份的动态集合名称。
例如:从"products"到"products2020"。
使用NESTJS,我必须导入";module.forFeature";具有指定的集合名称。
import { Module } from '@nestjs/common'
import { MongooseModule } from '@nestjs/mongoose'
@Module({
imports: [
MongooseModule.forFeature([
{
name: 'Products',
schema: ProductsSchema
}
])
],
controllers: [ProductsController],
providers: [ProductsService]
})
服务中的注入也会发生同样的情况:
import { Injectable } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model } from 'mongoose'
@Injectable()
export class ProductsService {
constructor(
@InjectModel('Products')
private readonly productsModel: Model<Products>
) {}
}
最后,这里是我的模式:
import { Schema } from 'mongoose'
export const ProductsSchema = new Schema(
{
_id: { Type: String, required: true },
code: String
},
{
collection: 'Products'
}
)
有什么方法可以实现动态命名吗?
非常感谢!
我遇到了一个类似的问题,我解决的方法是使用MongooseModule.forFeatureAsync
方法。模型和模式声明与nestjs文档中的相同。
@Module({
imports: [
MongooseModule.forFeatureAsync([
{
name: UsersModel.name,
imports: [EnvironmentModule],
inject: [EnvironmentService],
useFactory: (envService: EnvironmentService) => {
const env = envService.getEnv();
const schema = UsersSchema.set(
'collection',
`${env.countryCode}-users`,
);
return schema;
},
},
]),
...
],
providers: []
...
我一直在寻找解决这类问题的方法,但我遇到了困难,没有明确的方法。
以下(最小(代码实例化每个绑定到特定模型的服务,具体取决于country parameter
。即ServiceX
绑定到数据库X的模型,ServiceY
绑定到数据库Y 中的同一模型
但这是我设法做到的。你绝对可以做一个变通来满足你的需求
首先是模型/接口。常用于不同服务之间的
export interface User extends Document {
readonly username: string;
readonly password: string;
}
export const UserSchema = new mongoose.Schema(
{
_id: mongoose.ObjectId,
username: String,
password: String
},
{ collection: 'accounts', autoCreate: true }
);
对于不同数据库/集合中的每个模型,服务定义实际上是相同的
@Injectable()
export class XUserService implements OnModuleInit{
constructor(
private userModel: Model<User>,
) {
}
////////////////////////////////////////////////////////////////////////////
async onModuleInit(): Promise<any> {
console.log(`inside service dbname=: ${this.userModel.db.name} > ${this.userModel.collection.collectionName}` );
// await new this.userModel({_id: mongoose.Types.ObjectId(), username: 'test', password: 'test', flag: this.c}).save()
}
async insert(){
console.log(`inside service dbname=: ${this.userModel.db.name} > ${this.userModel.collection.collectionName}` );
await new this.userModel({
_id: mongoose.Types.ObjectId(),
username: this.userModel.db.name,
password: '0000'
}).save();
}
async findOne(): Promise<User>{
console.log(`inside service in : ${this.userModel.db.name} > ${this.userModel.collection.collectionName}` );
return this.userModel.findOne()
}
}
对于Module,我制作了一个DynamicModule
- 导入DBConnections
- 为每个需求创建一个模型(在我的情况下,每个数据库中有一个模型(
- 创建每个
Model
并将其绑定到一个Service
,因此服务的实例化将是正确的
@Module({
})
export class XUserModule{
static register( /*use can pass parameter here*/): DynamicModule{
return{
module: XUserModule,
imports: [
DatabaseModule
],
controllers: [
XUserController
],
providers: [
// Create Models here, #1 and #2 in two different database
{
provide: 'dz-'+'UserModel',
useFactory: (connection: Connection)=> {
return connection.model('User', UserSchema )
},
inject: [ dbname.shooffood('dz')+'Connection' ]
},{
provide: 'ca-'+'UserModel',
useFactory: (connection: Connection)=> {
return connection.model('User', UserSchema )
},
inject: [ dbname.shooffood('ca')+'Connection' ]
},
// Create Providers/Services for each Model and Inject the Model to the Service by `TokenString`
{
provide: 'dz' + XUserService.name,
useFactory: (m: any)=> {
console.log(m);
return new XUserService(m);
},
inject: [ 'dz-'+'UserModel' ]
},{
provide: 'ca' + XUserService.name,
useFactory: (m: any)=> {
console.log(m);
return new XUserService(m);
},
inject: [ 'ca-'+'UserModel' ]
}
],
// Export your service with the same `provide` name for later usage.
exports: [
'dz' + XUserService.name,
'ca' + XUserService.name
]
}
}
}
仅供参考,数据库模块看起来像常量dbname
是连接名称,uri
是连接字符串。
const databaseProviders = [
{
provide: dbname.admin+'Connection',
useFactory: (): Promise<typeof mongoose> => mongoose.createConnection(uri.admin),
},{
provide: dbname.system+'Connection',
useFactory: (): Promise<typeof mongoose> => mongoose.createConnection(uri.system),
},{
provide: dbname.shooffood('dz')+'Connection',
useFactory: (): Promise<typeof mongoose> => mongoose.createConnection(uri.dzfood),
},{
provide: dbname.shooffood('ca')+'Connection',
useFactory: (): Promise<typeof mongoose> => mongoose.createConnection(uri.cafood),
}
];
@Module({
providers: [
...databaseProviders
],
exports: [
dbname.admin+'Connection',
dbname.system+'Connection',
dbname.shooffood('dz')+'Connection',
dbname.shooffood('ca')+'Connection'
]
})
export class DatabaseModule {}
对于控制器,只有一个控制器通过请求参数:country
处理每个服务。但首先我必须列出应用程序中包含的所有可能的模型和服务。
@Controller(':country')
export class XUserController {
private byCountryServices = new Map();
constructor(
// Inject all required services by `tokenString`
@Inject('dz' + XUserService.name) private dzUserService: XUserService,
@Inject('ca' + XUserService.name) private caUserService: XUserService,
) {
// Add to `<key, value>` Map for easy by param access
this.byCountryServices.set('dz', this.dzUserService );
this.byCountryServices.set('ca', this.caUserService );
}
@Get('post')
async post(
@Param('country') c: string
): Promise<string>{
await this.byCountryServices.get(c).insert()
return 'inserted in ' + c;
}
@Get('get')
async get(
@Param('country') c: string
): Promise<string>{
console.log('param: ' + c)
return await this.byCountryServices.get(c).findOne()
}
}
最后,您使用在AppModule中导入模块XUserModule.register()
使用您的连接搜索客户端:
const client = this.productsModel.db.getClient();
const database = client.db("data base name");
const collection = database.collection("collection name");
const data = { test: "test" };
const insertOneResult = await collection.insertOne(data);