Mongoose实现事务时报session.withTransaction、endSession不是函数
触发报错的核心问题点
- 会话创建逻辑存在根本性错误:
startSession()是异步方法,原代码调用时未添加await,实际拿到的是未完成初始化的Promise对象,而非真正的MongoDB客户端会话实例,因此不存在withTransaction、endSession方法,直接触发两个TypeError报错。 - 连接对象获取路径错误:
mongoose.connect()的返回值是Mongoose全局实例,并非底层MongoClient实例,直接在Mongoose实例/连接对象上调用startSession不符合MongoDB驱动的调用规范。 - 事务操作未绑定会话:即使会话创建正常,执行
updateOne等数据库操作时未传入对应会话参数,操作不会被纳入事务管理范围,无法触发失败回滚逻辑。 - 版本兼容适配问题:
session.withTransaction自动重试辅助方法依赖Mongoose 5.2.0、对应mongodb驱动3.1.0及以上版本,若依赖版本过低也会触发方法不存在的报错。
修正后的可运行事务实现
实现前需先确认本地Mongoose版本≥5.2.0,可通过npm list mongoose命令查看版本,低版本需先完成升级。
// 基础配置 const CONSTANTS = { ADMIN_MONGO_URL: "mongodb://localhost:27017/admin?retryWrites=true&w=majority" } const mongoose = require('mongoose'); // 定义项目模型Schema const mongooseProjectSchema = new mongoose.Schema({ uuid: String, clientID: String, accumulatedProj: Array }) async function transactionCreateProject(newProjectJson) { const mongoConnectConfig = { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }; // 建立数据库连接 await mongoose.connect(CONSTANTS.ADMIN_MONGO_URL, mongoConnectConfig) const db = mongoose.connection; db.on('error', console.error.bind(console, 'MongoDB连接错误:')) const projectModel = mongoose.model('project', mongooseProjectSchema) // 修正1:从底层MongoClient实例创建会话,通过await等待会话初始化完成 const client = mongoose.connection.getClient(); const session = await client.startSession(); const transactionOptions = { readPreference: 'primary', readConcern: { level: 'local' }, writeConcern: { w: 'majority' } }; let transactionResult = null; try { // 修正2:会话实例上可正常调用withTransaction方法 transactionResult = await session.withTransaction(async () => { // 修正3:数据库操作显式传入会话参数,将操作纳入事务范围 const updateRes = await projectModel.updateOne( {'uuid': newProjectJson['clientID']}, {$push: {'accumulatedProj': {'uuid': newProjectJson.uuid}}}, { session: session } ); console.log("事务内更新操作执行结果:", updateRes) // 可在回调内直接返回需要向外传递的结果,供事务外层逻辑读取 return updateRes; }, transactionOptions); if (transactionResult) { console.log("事务执行成功,所有操作已正常提交"); } else { console.log("事务被主动中止"); } } catch (e) { console.log("事务因异常中止,所有操作已自动回滚:" + e.message); } finally { // 修正4:会话实例上可正常调用endSession方法释放资源 await session.endSession(); } return transactionResult; }
前置验证注意事项
- 确认MongoDB副本集状态正常,可通过mongo shell执行
rs.status()查看节点状态,确保副本集存在可用的PRIMARY节点,独立部署的单节点MongoDB不支持事务能力。 - 若升级Mongoose后仍报方法不存在,可通过
npm ls mongodb检查嵌套依赖的mongodb驱动版本,确保驱动版本≥3.1.0。
内容的提问来源于stack exchange,提问作者Sam Min Wong
相关产品推荐
相关产品推荐

