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

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(),会带来两个问题:

  1. 资源浪费:每次创建新的数据库连接,连接池的优势完全没发挥,频繁的连接/断开还会增加数据库负担
  2. 耦合度高:业务逻辑和数据库连接逻辑混在一起,不符合NestJS的模块化、依赖注入思想

上面的方案完全利用了NestJS的连接管理机制,既解耦又高效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:38:13