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

查询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会话已被提前关闭或过期,结合你的场景,大概率是以下两种情况:

  1. connectToDatabase内部提前终止会话:如果该函数中使用了startSession()或withSession(),且在返回client和database前就调用了session.endSession(),那么绑定了已结束会话的database实例在执行批量查询时会触发错误(单次查询可能因逻辑简化未严格校验会话状态)。
  2. 频繁创建/关闭客户端引发的异常:每次调用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 05:14:54