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

Mongoose聚合查询:获取用户详情及点赞/喜欢计数与关联数据

解决方案:用Mongoose聚合管道实现关联查询+统计计数

嘿,我正好有解决这个问题的办法!在Mongoose v5.6.10版本中,单纯用findOne()加populate()确实没法直接返回统计计数,不过咱们可以用**聚合管道(Aggregation Pipeline)**来实现——它能把关联查询和统计计算一步搞定,完美满足你的需求。

首先先明确下咱们的Schema结构(如果和你的实际代码有出入,调整对应字段即可):

// ProfileReaction Schema
const profileReactionSchema = new mongoose.Schema({
  type: { type: String, enum: ['like', 'love'], required: true },
  user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
  // 其他自定义字段...
});
const ProfileReaction = mongoose.model('ProfileReaction', profileReactionSchema);

// User Schema
const userSchema = new mongoose.Schema({
  name: String,
  email: String,
  // 关联用户的所有Reaction记录
  profileReactions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'ProfileReaction' }]
});
const User = mongoose.model('User', userSchema);

方案一:查询单个用户详情+关联Reaction+统计计数

这个方案适合你需要查询某一个特定用户的场景,通过$lookup关联Reaction数据,再用$filter和$size统计点赞、喜欢的数量:

const targetUserId = '你的目标用户ID'; // 替换成实际用户ID

User.aggregate([
  // 第一步:匹配目标用户
  { $match: { _id: mongoose.Types.ObjectId(targetUserId) } },
  // 第二步:关联ProfileReaction集合,获取所有关联的反应数据
  {
    $lookup: {
      from: 'profilereactions', // 注意这里是集合的实际名称(模型名默认转小写复数)
      localField: 'profileReactions',
      foreignField: '_id',
      as: 'reactions' // 关联后的数据会存在这个字段里
    }
  },
  // 第三步:添加统计字段,计算点赞数和喜欢数
  {
    $addFields: {
      noOfLikes: {
        $size: {
          $filter: {
            input: '$reactions',
            cond: { $eq: ['$$this.type', 'like'] } // 筛选type为like的记录
          }
        }
      },
      noOfLoves: {
        $size: {
          $filter: {
            input: '$reactions',
            cond: { $eq: ['$$this.type', 'love'] } // 筛选type为love的记录
          }
        }
      }
    }
  }
])
.then(result => {
  // 结果数组的第一个元素就是包含统计信息的用户详情
  console.log('用户详情+统计数据:', result[0]);
})
.catch(err => {
  console.error('查询出错:', err);
});

执行后,你会得到一个包含以下内容的用户对象:

  • 用户本身的所有字段(name、email等)
  • reactions数组:所有关联的ProfileReaction数据
  • noOfLikes:点赞的总数量
  • noOfLoves:喜欢的总数量

方案二:批量统计所有用户的点赞/喜欢数+关联用户详情

如果你需要批量获取多个用户的统计数据,这个方案会更高效:先统计每个用户的Reaction数量,再关联用户的详情信息:

ProfileReaction.aggregate([
  // 第一步:按用户ID和反应类型分组,统计数量
  {
    $group: {
      _id: { userId: '$user', type: '$type' },
      count: { $sum: 1 }
    }
  },
  // 第二步:把同一用户的不同类型统计结果合并
  {
    $group: {
      _id: '$_id.userId',
      reactionCounts: { $push: { k: '$_id.type', v: '$count' } }
    }
  },
  // 第三步:把数组格式的统计结果转换成对象(方便取值)
  {
    $addFields: {
      reactionCounts: { $arrayToObject: '$reactionCounts' }
    }
  },
  // 第四步:关联User集合,获取用户详情
  {
    $lookup: {
      from: 'users',
      localField: '_id',
      foreignField: '_id',
      as: 'userInfo'
    }
  },
  // 第五步:展开用户详情数组(每个用户只有一条数据)
  { $unwind: '$userInfo' },
  // 第六步:把统计数合并到用户详情对象中
  {
    $addFields: {
      'userInfo.noOfLikes': { $ifNull: ['$reactionCounts.like', 0] }, // 没有点赞则显示0
      'userInfo.noOfLoves': { $ifNull: ['$reactionCounts.love', 0] } // 没有喜欢则显示0
    }
  },
  // 第七步:把用户详情作为最终返回的根对象
  { $replaceRoot: { newRoot: '$userInfo' } }
])
.then(results => {
  console.log('批量用户统计数据:', results);
})
.catch(err => {
  console.error('批量查询出错:', err);
});

这个方案会返回所有用户的列表,每个用户对象都包含noOfLikes和noOfLoves字段,同时保留用户本身的所有详情。

注意事项

  • 确保$lookup里的from参数是集合的实际名称(Mongoose默认会把模型名转成小写复数,比如ProfileReaction对应profilereactions)
  • 如果你的Schema关联逻辑和示例不同(比如ProfileReaction是通过其他字段关联User),只需要调整localField和foreignField即可
  • Mongoose v5.6.10完全支持上述聚合操作,不用担心兼容性问题

内容的提问来源于stack exchange,提问作者Hemadri Dasari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 11:22:42