ack*_*ser 6 mongoose mongodb node.js typescript nestjs
使用Nestjs 6.x、Mongoose、Mongo等开发一个项目...关于后端,在我的用例中,我必须根据来自某些请求的某些条件/参数更改我的数据库之一的连接。
基本上,我有这个
mongoose.createConnection('mongodb://127.0.0.1/whatever-a', { useNewUrlParser: true })
Run Code Online (Sandbox Code Playgroud)
我想改为,例如
mongoose.createConnection('mongodb://127.0.0.1/whatever-b', { useNewUrlParser: true })
Run Code Online (Sandbox Code Playgroud)
因此,我在 Nestjs 中有第一个提供者
export const databaseProviders = [
{
provide: 'DbConnectionToken',
useFactory: async (): Promise<typeof mongoose> =>
await mongoose.createConnection('mongodb://127.0.0.1/whatever', { useNewUrlParser: true })
}
Run Code Online (Sandbox Code Playgroud)
我研究了一段时间,发现在Nestjs 6.x版本中,提供程序请求允许我动态修改每个请求某些提供程序的注入。
不管怎样,我不知道如何实现我的改变,也不知道它是否会起作用,以防我实现这一目标
有人可以帮助或指导我吗?提前谢谢了。
您可以使用 Nest 的内置 Mongoose 包执行以下操作:
/*************************
* mognoose.service.ts
*************************/
import { Inject, Injectable, Scope } from '@nestjs/common';
import { MongooseOptionsFactory, MongooseModuleOptions } from '@nestjs/mongoose';
import { REQUEST } from '@nestjs/core';
import { Request } from '@nestjs/common';
@Injectable({ scope: Scope.REQUEST })
export class MongooseConfigService implements MongooseOptionsFactory {
constructor(
@Inject(REQUEST) private readonly request: Request,) {
}
createMongooseOptions(): MongooseModuleOptions {
return {
uri: request.params.uri, // Change this to whatever you want; you have full access to the request object.
};
}
}
/*************************
* mongoose.module.ts
*************************/
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { MongooseConfigService } from 'mognoose.service';
@Module({
imports: [
MongooseModule.forRootAsync({
useClass: MongooseConfigService,
}),
]
})
export class DbModule {}
Run Code Online (Sandbox Code Playgroud)
然后,您可以将任何您想要的内容附加到请求中,并根据请求更改数据库;因此使用Scope.REQUEST. 您可以在其文档中阅读有关Injection Scopes的更多信息。
编辑:如果您遇到 PassportJS(或任何其他包)的问题或请求为空,这似乎是与 PassportJS(或其他包)不支持请求范围相关的错误;您可以在 GitHub 上阅读有关 PassportJS 的更多信息。
小智 3
我为Nest-mongodb做了一个简单的实现,
主要更改在 mongo-core.module.ts 中,我将连接存储在映射中并在可用时使用它们,而不是每次都创建新连接。
import {
Module,
Inject,
Global,
DynamicModule,
Provider,
OnModuleDestroy,
} from '@nestjs/common';
import { ModuleRef } from '@nestjs/core';
import { MongoClient, MongoClientOptions } from 'mongodb';
import {
DEFAULT_MONGO_CLIENT_OPTIONS,
MONGO_MODULE_OPTIONS,
DEFAULT_MONGO_CONTAINER_NAME,
MONGO_CONTAINER_NAME,
} from './mongo.constants';
import {
MongoModuleAsyncOptions,
MongoOptionsFactory,
MongoModuleOptions,
} from './interfaces';
import { getClientToken, getContainerToken, getDbToken } from './mongo.util';
import * as hash from 'object-hash';
@Global()
@Module({})
export class MongoCoreModule implements OnModuleDestroy {
constructor(
@Inject(MONGO_CONTAINER_NAME) private readonly containerName: string,
private readonly moduleRef: ModuleRef,
) {}
static forRoot(
uri: string,
dbName: string,
clientOptions: MongoClientOptions = DEFAULT_MONGO_CLIENT_OPTIONS,
containerName: string = DEFAULT_MONGO_CONTAINER_NAME,
): DynamicModule {
const containerNameProvider = {
provide: MONGO_CONTAINER_NAME,
useValue: containerName,
};
const connectionContainerProvider = {
provide: getContainerToken(containerName),
useFactory: () => new Map<any, MongoClient>(),
};
const clientProvider = {
provide: getClientToken(containerName),
useFactory: async (connections: Map<any, MongoClient>) => {
const key = hash.sha1({
uri: uri,
clientOptions: clientOptions,
});
if (connections.has(key)) {
return connections.get(key);
}
const client = new MongoClient(uri, clientOptions);
connections.set(key, client);
return await client.connect();
},
inject: [getContainerToken(containerName)],
};
const dbProvider = {
provide: getDbToken(containerName),
useFactory: (client: MongoClient) => client.db(dbName),
inject: [getClientToken(containerName)],
};
return {
module: MongoCoreModule,
providers: [
containerNameProvider,
connectionContainerProvider,
clientProvider,
dbProvider,
],
exports: [clientProvider, dbProvider],
};
}
static forRootAsync(options: MongoModuleAsyncOptions): DynamicModule {
const mongoContainerName =
options.containerName || DEFAULT_MONGO_CONTAINER_NAME;
const containerNameProvider = {
provide: MONGO_CONTAINER_NAME,
useValue: mongoContainerName,
};
const connectionContainerProvider = {
provide: getContainerToken(mongoContainerName),
useFactory: () => new Map<any, MongoClient>(),
};
const clientProvider = {
provide: getClientToken(mongoContainerName),
useFactory: async (
connections: Map<any, MongoClient>,
mongoModuleOptions: MongoModuleOptions,
) => {
const { uri, clientOptions } = mongoModuleOptions;
const key = hash.sha1({
uri: uri,
clientOptions: clientOptions,
});
if (connections.has(key)) {
return connections.get(key);
}
const client = new MongoClient(
uri,
clientOptions || DEFAULT_MONGO_CLIENT_OPTIONS,
);
connections.set(key, client);
return await client.connect();
},
inject: [getContainerToken(mongoContainerName), MONGO_MODULE_OPTIONS],
};
const dbProvider = {
provide: getDbToken(mongoContainerName),
useFactory: (
mongoModuleOptions: MongoModuleOptions,
client: MongoClient,
) => client.db(mongoModuleOptions.dbName),
inject: [MONGO_MODULE_OPTIONS, getClientToken(mongoContainerName)],
};
const asyncProviders = this.createAsyncProviders(options);
return {
module: MongoCoreModule,
imports: options.imports,
providers: [
...asyncProviders,
clientProvider,
dbProvider,
containerNameProvider,
connectionContainerProvider,
],
exports: [clientProvider, dbProvider],
};
}
async onModuleDestroy() {
const clientsMap: Map<any, MongoClient> = this.moduleRef.get<
Map<any, MongoClient>
>(getContainerToken(this.containerName));
if (clientsMap) {
await Promise.all(
[...clientsMap.values()].map(connection => connection.close()),
);
}
}
private static createAsyncProviders(
options: MongoModuleAsyncOptions,
): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncOptionsProvider(options)];
} else if (options.useClass) {
return [
this.createAsyncOptionsProvider(options),
{
provide: options.useClass,
useClass: options.useClass,
},
];
} else {
return [];
}
}
private static createAsyncOptionsProvider(
options: MongoModuleAsyncOptions,
): Provider {
if (options.useFactory) {
return {
provide: MONGO_MODULE_OPTIONS,
useFactory: options.useFactory,
inject: options.inject || [],
};
} else if (options.useExisting) {
return {
provide: MONGO_MODULE_OPTIONS,
useFactory: async (optionsFactory: MongoOptionsFactory) =>
await optionsFactory.createMongoOptions(),
inject: [options.useExisting],
};
} else if (options.useClass) {
return {
provide: MONGO_MODULE_OPTIONS,
useFactory: async (optionsFactory: MongoOptionsFactory) =>
await optionsFactory.createMongoOptions(),
inject: [options.useClass],
};
} else {
throw new Error('Invalid MongoModule options');
}
}
}
Run Code Online (Sandbox Code Playgroud)
查看完整实施情况
| 归档时间: |
|
| 查看次数: |
10022 次 |
| 最近记录: |