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

MongoDB分组聚合:获取$max值及其计数与占比,含关联字段需求

解决MongoDB聚合中关联字段name缺失的问题

嘿,我看到你现在的问题是分组聚合后,l1字段的关联name没出现在结果里——这是因为原来的聚合流程没有把关联集合的name数据拉进来,毕竟Mongoose的populate()没法直接在聚合管道里用,得用MongoDB原生的$lookup来做关联查询。我来帮你调整聚合语句,同时满足你要的最大值、出现次数和占比需求:

完整聚合语句

db.getCollection("test").aggregate([
  // 第一步:匹配目标文档
  { "$match": { "doc_id": 1.0 } },
  // 第二步:关联l1对应的集合,拉取name字段(替换成你的l1集合真实名称)
  {
    "$lookup": {
      "from": "l1_collection",
      "localField": "l1",
      "foreignField": "_id",
      "as": "l1_info"
    }
  },
  // 展开关联后的数组(因为lookup返回的是数组,每个文档只关联一个l1所以直接unwind)
  { "$unwind": "$l1_info" },
  // 第三步:按name分组,同时保存必要的统计数据和l1的详细信息
  {
    "$group": {
      "_id": { "name": "$name" },
      "total": { "$sum": "$amount" },
      "group_total_count": { "$sum": 1 }, // 分组内的总记录数
      "l1_max_id": { "$max": "$l1" }, // 分组内l1的最大值(id)
      // 保存每个l1的id和对应的name,方便后续过滤
      "l1_details": {
        "$push": {
          "id": "$l1",
          "name": "$l1_info.name"
        }
      }
    }
  },
  // 第四步:格式化结果,提取max对应的name、计算次数和占比,甚至生成你要的显示文本
  {
    "$project": {
      "_id": 1,
      "total": 1,
      "l1": {
        "_id": "$l1_max_id",
        "name": {
          // 从l1_details里过滤出id等于max的项,取出name
          "$arrayElemAt": [
            {
              "$map": {
                "input": {
                  "$filter": {
                    "input": "$l1_details",
                    "cond": { "$eq": ["$$this.id", "$l1_max_id"] }
                  }
                },
                "as": "item",
                "in": "$$item.name"
              }
            },
            0
          ]
        },
        "count": {
          // 计算max l1在分组内的出现次数
          "$size": {
            "$filter": {
              "input": "$l1_details",
              "cond": { "$eq": ["$$this.id", "$l1_max_id"] }
            }
          }
        },
        "percent": {
          // 计算占比(次数/分组总记录数)
          "$divide": [
            {
              "$size": {
                "$filter": {
                  "input": "$l1_details",
                  "cond": { "$eq": ["$$this.id", "$l1_max_id"] }
                }
              }
            },
            "$group_total_count"
          ]
        }
      },
      // 可选:生成你要的格式化显示文本,比如 'IT - (25%) Total 4/16'
      "l1_display": {
        "$concat": [
          {
            "$arrayElemAt": [
              {
                "$map": {
                  "input": {
                    "$filter": {
                      "input": "$l1_details",
                      "cond": { "$eq": ["$$this.id", "$l1_max_id"] }
                    }
                  },
                  "as": "item",
                  "in": "$$item.name"
                }
              },
              0
            ]
          },
          " - (",
          { "$toString": { "$multiply": ["$l1.percent", 100] } },
          "%) Total ",
          { "$toString": "$l1.count" },
          "/",
          { "$toString": "$group_total_count" }
        ]
      }
    }
  }
]);

关键步骤说明

  • $lookup + $unwind:这是核心,把l1关联集合里的name字段拉到当前聚合流程中,解决了关联字段缺失的问题。记得把from的值替换成你实际存储l1数据的集合名称。
  • 分组阶段的l1_details:保存每个分组内所有l1的id和name,这样后续才能找到最大值对应的name,同时统计出现次数。
  • project阶段的过滤与计算:通过$filter筛选出对应max id的l1项,用$arrayElemAt取出name;用$size统计出现次数;用$divide计算占比,最后还可以用$concat生成你需要的格式化显示文本。

示例返回结果

{
  "_id": { "name": "xzy" },
  "total": 35.0,
  "l1": {
    "_id": "4343920239201W",
    "name": "IT",
    "count": 4.0,
    "percent": 0.25
  },
  "l1_display": "IT - (25%) Total 4/16"
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:21:26