NestJS中创建无Schema的Mongoose Provider并获取db.stats()
在NestJS中优雅获取Mongoose数据库统计信息(db.stats())
我完全懂你的困扰——跟着NestJS官方的Mongoose教程走,大部分内容都是围绕模型操作展开的,想直接拿到db.stats()这种数据库级别的统计数据,确实容易卡壳。你自己写的那种每次手动连接又断开的方式,不仅耦合度高,还浪费数据库连接资源,完全不符合NestJS的依赖注入和连接管理思想。
下面给你两种符合NestJS架构风格的解决方案,都是基于框架已经维护好的Mongoose连接来实现的:
方法一:注入Connection对象(推荐,最贴合NestJS风格)
NestJS的MongooseModule已经帮我们维护了一个单例的数据库连接,我们只需要在Service中注入Connection对象,就能直接调用数据库级别的API。
步骤1:确保你的数据库模块已正确配置
首先在你的数据库模块(比如DatabaseModule)里配置好Mongoose连接,用forRootAsync结合配置服务是最佳实践:
import { Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { ConfigService } from '@nestjs/config'; @Module({ imports: [ MongooseModule.forRootAsync({ useFactory: (configService: ConfigService) => ({ uri: configService.get<string>('base.mongodb.uri'), // 可以添加其他Mongoose配置项,比如连接池大小等 }), inject: [ConfigService], }), ], }) export class DatabaseModule {}
步骤2:在Service中注入Connection并获取统计信息
import { Injectable } from '@nestjs/common'; import { Connection } from 'mongoose'; import { InjectConnection } from '@nestjs/mongoose'; // 假设你的IDatabaseStats类型定义如下 interface IDatabaseStats { dbName: string; collectionCount: number; documentCount: number; dataSize: number; // 其他你需要的统计字段 } @Injectable() export class DatabaseStatsService { // 注入NestJS维护的Mongoose连接 constructor(@InjectConnection() private readonly connection: Connection) {} async getStatsFromDatabase(): Promise<IDatabaseStats> { // 直接通过已有的连接调用db.stats() const rawStats = await this.connection.db.stats(); // 将原始统计数据映射到你的自定义类型 return { dbName: rawStats.db, collectionCount: rawStats.collections, documentCount: rawStats.objects, dataSize: rawStats.dataSize, }; } }
方法二:直接注入mongoose实例(如果你更习惯原生Mongoose API)
如果你更倾向于直接使用mongoose的全局实例,也可以通过@InjectMongoose()装饰器注入:
import { Injectable } from '@nestjs/common'; import mongoose from 'mongoose'; import { InjectMongoose } from '@nestjs/mongoose'; @Injectable() export class DatabaseStatsService { constructor(@InjectMongoose() private readonly mongoose: typeof mongoose) {} async getStatsFromDatabase(): Promise<IDatabaseStats> { // 这里的connection是NestJS已经初始化好的活跃连接 const rawStats = await this.mongoose.connection.db.stats(); // 映射字段返回... return { dbName: rawStats.db, collectionCount: rawStats.collections, documentCount: rawStats.objects, dataSize: rawStats.dataSize, }; } }
针对多数据库连接的情况
如果你项目里配置了多个Mongoose连接,只需要在注入时指定连接名称即可:
// 配置多连接时指定name MongooseModule.forRootAsync({ name: 'secondaryDb', useFactory: (configService: ConfigService) => ({ uri: configService.get<string>('base.mongodb.secondaryUri'), }), inject: [ConfigService], }) // 注入时指定对应名称 constructor(@InjectConnection('secondaryDb') private readonly connection: Connection) {}
为什么你之前的代码不够优雅?
你之前每次调用都手动执行mongoose.connect()和mongoose.disconnect(),会带来两个问题:
- 资源浪费:每次创建新的数据库连接,连接池的优势完全没发挥,频繁的连接/断开还会增加数据库负担
- 耦合度高:业务逻辑和数据库连接逻辑混在一起,不符合NestJS的模块化、依赖注入思想
上面的方案完全利用了NestJS的连接管理机制,既解耦又高效。
内容的提问来源于stack exchange,提问作者aperdizs
相关产品推荐
相关产品推荐

