Mongoose事务调用find().session(session)返回IllegalOperation错误如何解决
问题原因与解决方案
错误根因梳理
SystemRole.find()返回的是匹配结果数组,即使只有1条Admin角色匹配,返回值也是数组格式,不能直接作为后续查询的参数,应改为findOne()获取单个角色文档。
- MongoDB原生没有
$contains查询操作符,查询数组包含指定ID时,直接等值匹配即可(MongoDB会自动扫描数组内元素),且需要传入角色的_id字段,而非完整的角色文档。
- MongoDB原生没有
- 字段名存在不匹配风险:你提到User Schema中存储角色ID的数组字段名为
systemRole,但查询条件中写的是systemRoles,请先核对Schema定义修正字段名。
- 字段名存在不匹配风险:你提到User Schema中存储角色ID的数组字段名为
- 基础部署要求:MongoDB事务仅支持副本集、分片集群部署,单节点MongoDB实例不支持事务,这也是触发
IllegalOperation错误的常见原因。
- 基础部署要求:MongoDB事务仅支持副本集、分片集群部署,单节点MongoDB实例不支持事务,这也是触发
修正后代码示例
const session = await mongoose.startSession(); try { await session.startTransaction(); // 改为findOne获取单个Admin角色 const systemRole = await SystemRole.findOne( { isActive: true, roleName: "Admin", } ).session(session); if (!systemRole) { throw new Error("未找到Admin角色"); } // 修正查询操作符、传入角色_id、核对字段名 const adminUsers = await User.find( { isActive: true, // 此处如果你的字段名确实是systemRole请去掉末尾的s systemRoles: systemRole._id, } ).session(session); // 此处编写后续发送通知、其他事务操作逻辑 // ... // 提交事务 await session.commitTransaction(); } catch (err) { // 出错回滚事务 await session.abortTransaction(); throw err; } finally { // 最终关闭session await session.endSession(); }
额外校验点
如果调整代码后仍报错,先确认你的MongoDB部署模式:单节点实例可以通过转为单节点副本集的方式开启事务支持,操作无需新增节点,仅需修改启动配置添加副本集参数即可。
内容的提问来源于stack exchange,提问作者Kirubel
相关产品推荐
相关产品推荐

