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

MongoDB聚合查询求助:统计冥想应用中最受欢迎的冥想内容

MongoDB聚合查询求助:统计冥想应用中最受欢迎的冥想内容

嘿,我懂你现在的烦恼——要从两个关联的集合里统计出最受欢迎的冥想内容,确实得把聚合管道的步骤捋清楚才行。你之前试过$unwind和$lookup没成功,大概率是因为字段类型不匹配或者管道顺序不对,我来给你拆解下正确的查询逻辑:

首先,核心思路是先把用户的每条收听记录拆出来,统计每个冥想ID的收听次数,再关联冥想的详细信息,最后排序。这里要注意一个关键细节:你的users集合里存的冥想ID是字符串格式,而meditations集合里的_id是ObjectId类型,直接关联会匹配不上,所以必须先做类型转换。

下面是完整的聚合查询代码:

db.users.aggregate([
  // 1. 展开每个用户的收听记录数组,每条记录对应一次收听行为
  {
    $unwind: "$userProgress.meditationsPracticed"
  },
  // 2. 把字符串格式的冥想ID转换成ObjectId,方便后续关联meditations集合
  {
    $addFields: {
      "meditationObjectId": {
        $toObjectId: "$userProgress.meditationsPracticed.id"
      }
    }
  },
  // 3. 按冥想ID分组,统计每个冥想的总收听次数
  {
    $group: {
      _id: "$meditationObjectId",
      listenCount: { $sum: 1 }
    }
  },
  // 4. 关联meditations集合,获取冥想的详细信息(名称、时长等)
  {
    $lookup: {
      from: "meditations",
      localField: "_id",
      foreignField: "_id",
      as: "meditationInfo"
    }
  },
  // 5. 展开关联后的冥想信息数组(因为$lookup返回的是数组)
  {
    $unwind: "$meditationInfo"
  },
  // 6. 按收听次数降序排序,最受欢迎的排在最前面
  {
    $sort: { listenCount: -1 }
  },
  // 7. 可选:调整输出字段,只保留需要的内容
  {
    $project: {
      _id: 0,
      listenCount: 1,
      meditationName: "$meditationInfo.name",
      meditationDuration: "$meditationInfo.duration"
    }
  }
])

我来给你解释下每一步的作用:

  • $unwind:把每个用户的meditationsPracticed数组拆成单独的文档,这样每条文档就代表一次独立的收听行为。
  • $addFields:将字符串ID转为ObjectId,这步是关键!如果跳过,$lookup会因为类型不匹配查不到数据,这很可能是你之前失败的原因。
  • $group:按转换后的冥想ID分组,用$sum:1统计每个ID出现的次数,也就是总收听量。
  • $lookup:关联meditations集合,把对应冥想的详细信息拉取过来。
  • $unwind:因为$lookup返回的是数组,展开后每条文档对应一个带详细信息的统计结果。
  • $sort:按收听次数从高到低排序,直接得到最受欢迎的冥想列表。
  • $project:可选步骤,用来整理输出格式,去掉不需要的字段,让结果更清晰。

如果你的users集合里的冥想ID已经是ObjectId类型(不是字符串),那可以去掉$addFields这一步,直接用$userProgress.meditationsPracticed.id来分组就行。

试试这个查询,应该就能得到你想要的结果啦!

备注:内容来源于stack exchange,提问作者Daniel Amram

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 11:20:28