查询MongoDB时出现Cannot use a session that has ended错误求助
解决MongoDB查询所有文档时出现"Cannot use a session that has ended"错误
错误信息
106 | * not subject to semantic versioning compatibility guarantees and may change at any time. 107 | * 108 | * @public 109 | **/ 110 | constructor(message, options) { 111 | super(message, options); ^ error: Cannot use a session that has ended at new MongoError (C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\error.js:111:9) at new MongoDriverError (C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\error.js:209:9) at new MongoAPIError (C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\error.js:238:9) at new MongoExpiredSessionError (C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\error.js:403:9) at applySession (C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\sessions.js:708:16) at prepareCommand (C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\cmap\connection.js:169:49) at C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\cmap\connection.js:259:30 at C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\cmap\connection.js:313:26 at command (C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\cmap\connection.js:311:23) at C:\Users\Utente\Desktop\SkyForce Helper\node_modules\mongodb\lib\sdam\server.js:167:40
问题代码
export async function returnAllRep(): Promise<string[]> { const { client, database } = await connectToDatabase(); const collection = database.collection('chains'); try { const docs = await collection.find().toArray(); const ids = docs.map(doc => doc.id); return ids; } catch (error) { console.error('Errore durante la recuperazione dei documenti:', error); throw error; } finally { await client.close(); } }
问题描述
已确认数据库连接成功,但查询所有文档时触发会话已结束错误,仅查询单个文档时可正常运行,需要获取所有文档的id字段。
错误原因
这个错误的核心是执行批量查询时依赖的MongoDB会话已被提前关闭或过期,结合你的场景,大概率是以下两种情况:
connectToDatabase内部提前终止会话:如果该函数中使用了startSession()或withSession(),且在返回client和database前就调用了session.endSession(),那么绑定了已结束会话的database实例在执行批量查询时会触发错误(单次查询可能因逻辑简化未严格校验会话状态)。- 频繁创建/关闭客户端引发的异常:每次调用
returnAllRep都新建客户端并在finally中关闭,当查询大量文档时,游标迭代过程中可能因连接池或会话管理的延迟,导致会话被提前回收。
解决方法
方法一:修正connectToDatabase实现
确保函数不提前结束会话,直接返回正常连接的客户端和数据库实例:
import { MongoClient } from 'mongodb'; async function connectToDatabase() { const uri = '你的MongoDB连接字符串'; const client = new MongoClient(uri); // 仅在未连接时执行连接操作 if (!client.isConnected()) { await client.connect(); } const database = client.db('你的数据库名称'); return { client, database }; }
方法二:复用MongoDB客户端(推荐)
频繁创建和关闭客户端会降低性能且易引发会话问题,建议全局复用连接:
import { MongoClient } from 'mongodb'; // 全局维护客户端实例 let client; async function connectToDatabase() { if (!client) { const uri = '你的MongoDB连接字符串'; client = new MongoClient(uri); await client.connect(); console.log('MongoDB连接成功'); } const database = client.db('你的数据库名称'); return { client, database }; } // 修改查询函数,不再手动关闭客户端 export async function returnAllRep(): Promise<string[]> { const { database } = await connectToDatabase(); const collection = database.collection('chains'); try { const docs = await collection.find().toArray(); const ids = docs.map(doc => doc.id); return ids; } catch (error) { console.error('Errore durante la recuperazione dei documenti:', error); throw error; } } // 应用退出时统一关闭客户端(可选,如在Node.js进程退出钩子中) process.on('SIGINT', async () => { if (client) { await client.close(); console.log('MongoDB客户端已关闭'); process.exit(0); } });
方法三:显式管理会话(若需使用会话场景)
如果业务需要使用会话(如事务),需确保会话在所有操作完成后再结束:
export async function returnAllRep(): Promise<string[]> { const { client, database } = await connectToDatabase(); const collection = database.collection('chains'); let session; try { session = client.startSession(); // 将会话绑定到查询操作 const docs = await collection.find().session(session).toArray(); const ids = docs.map(doc => doc.id); return ids; } catch (error) { console.error('Errore durante la recuperazione dei documenti:', error); throw error; } finally { // 操作完成后结束会话 if (session) await session.endSession(); // 若复用客户端则注释此行,否则可关闭 // await client.close(); } }
内容的提问来源于stack exchange,提问作者Matteo Donati
相关产品推荐
相关产品推荐

