MongoDB Mongoose取消关注Post Hook聚合管道失效问题排查
问题分析与解决方案
问题根源
在Mongoose的findOneAndRemove post钩子中,this指向的是Query对象,而非Followers文档实例。因此this.constructor对应的是Query类,不是你定义的Followers模型,自然找不到AdjustFollowersFollowing静态方法,这就是报错的核心原因。
另外,你的AdjustFollowersFollowing是异步函数,但原post钩子未使用async/await,会导致函数未执行完成就结束,可能引发潜在的异步问题。
修复步骤
1. 修改post钩子,正确调用静态方法
有两种可靠方式获取Followers模型并调用静态方法:
- 直接使用你定义好的Followers模型(假设导出的模型名为
Followers) - 通过Query对象的
model()方法获取对应模型
示例代码:
// 方式一:直接调用已定义的模型 followersschema.post('findOneAndRemove', async function() { const { followedid, followingid } = this._conditions; console.log(followedid, followingid); await Followers.AdjustFollowersFollowing(followedid, followingid); }); // 方式二:通过Query对象获取模型 followersschema.post('findOneAndRemove', async function() { const { followedid, followingid } = this._conditions; console.log(followedid, followingid); const FollowersModel = this.model('Followers'); // 传入模型名称 await FollowersModel.AdjustFollowersFollowing(followedid, followingid); });
2. 完善AdjustFollowersFollowing函数的容错逻辑
当前代码中,如果聚合结果为空数组(比如用户取消关注后粉丝数变为0),访问statsfollowedid[0].numFollowed会直接报错,需要添加空值处理:
followersschema.statics.AdjustFollowersFollowing = async function(FOLLOWEDID, FOLLOWINGID){ try { const statsfollowedid = await this.aggregate([ { $match: { followedid: FOLLOWEDID } }, { $group: { _id: FOLLOWEDID, numFollowed: { $sum: 1 } } } ]); const numFollowed = statsfollowedid.length > 0 ? statsfollowedid[0].numFollowed : 0; const statsfollowingid = await this.aggregate([ { $match: { followingid: FOLLOWINGID } }, { $group: { _id: FOLLOWINGID, numFollowing: { $sum: 1 } } } ]); const numFollowing = statsfollowingid.length > 0 ? statsfollowingid[0].numFollowing : 0; await User.findByIdAndUpdate(FOLLOWEDID, { numfollowers: numFollowed }); await User.findByIdAndUpdate(FOLLOWINGID, { numfollowing: numFollowing }); } catch(err) { console.error('调整关注数失败:', err); } }
3. 确认模型编译正确
确保你已正确编译并导出Followers模型:
const mongoose = require('mongoose'); const Followers = mongoose.model('Followers', followersschema); module.exports = Followers;
额外优化建议
- 使用事务保证更新操作的原子性,避免中途出错导致粉丝数和关注数不一致;
- 将两个聚合查询用
Promise.all并行执行,提升性能:
const [statsFollowed, statsFollowing] = await Promise.all([ this.aggregate([/* 被关注者聚合逻辑 */]), this.aggregate([/* 关注者聚合逻辑 */]) ]);
内容的提问来源于stack exchange,提问作者Jaz
相关产品推荐
相关产品推荐

