NestJS中MongoDB动态集合查询遇Mongoose超时错误求助
解决NestJS中MongoDB动态集合查询的超时问题
问题根源
你当前的实现每次调用DynamicSchema都会创建全新的Mongoose模型,且直接使用全局mongoose.model()方法,存在两个核心问题:
- 重复注册同名模型(均为'Log')会引发Mongoose内部冲突
- 动态创建的模型未关联到NestJS初始化好的数据库连接池,导致数据库操作处于缓冲等待状态,最终触发超时
解决方案
核心思路是复用已创建的模型并绑定到NestJS的数据库连接,具体步骤如下:
1. 注入NestJS的Mongoose连接
在服务中通过@InjectConnection()获取Nest初始化的数据库连接,确保动态模型使用正确的连接池。
2. 实现模型复用逻辑
每次创建前检查连接中是否已存在对应集合的模型,避免重复创建;用集合名称作为模型名,保证唯一性。
3. 替换废弃的计数方法
Mongoose已废弃count()方法,改用countDocuments()替代。
完整代码示例
import { Injectable } from '@nestjs/common'; import { InjectConnection } from '@nestjs/mongoose'; import { Connection } from 'mongoose'; import { Prop, SchemaFactory } from '@nestjs/mongoose'; @Injectable() export class LogService { constructor(@InjectConnection() private readonly connection: Connection) {} // 获取动态日志模型,复用已存在的模型 private getDynamicLogModel(collectionName: string) { // 检查当前连接中是否已注册该集合的模型 if (this.connection.models[collectionName]) { return this.connection.models[collectionName]; } // 动态定义Schema @Schema({ collection: collectionName }) class DynamicLog { @Prop() level: string; @Prop() message: string; } const dynamicLogSchema = SchemaFactory.createForClass(DynamicLog); // 以集合名作为模型名注册,避免重复冲突 return this.connection.model(collectionName, dynamicLogSchema); } async queryLogs(gatewayId: string, options: Record<string, any>) { const dynamicModel = this.getDynamicLogModel(gatewayId); // 执行查询并强制调用exec()确保Promise正确解析 const logs = await dynamicModel.find(options).limit(2).exec(); const totalDocuments = await dynamicModel.countDocuments(options).exec(); return { logs, totalDocuments }; } }
关键优化点说明
- 复用模型:避免重复创建模型导致的连接冲突和资源浪费
- 绑定Nest连接:确保模型使用Nest初始化的数据库连接,而非全局未初始化的连接
- 显式调用
exec():Mongoose的查询构建器需要通过exec()返回标准Promise,避免异步处理异常
内容的提问来源于stack exchange,提问作者Rafael
相关产品推荐
相关产品推荐

