MongoDB聚合操作:替代$unwind实现属性分组统计需求
MongoDB聚合统计RAM规格(替代$unwind方案)
聚合管道代码
db.phones.aggregate([ // 提取单条记录中RAM规格的value值 { $project: { ram_value: { $first: { $map: { input: { $filter: { input: "$specs", cond: { $eq: ["$$this.code", "ram"] } } }, as: "spec", in: "$$spec.value" } } } } }, // 过滤无RAM规格的记录 { $match: { ram_value: { $ne: null } } }, // 按RAM值分组统计出现次数 { $group: { _id: "$ram_value", doc_count: { $sum: 1 } } }, // 转换为key-doc_count结构 { $project: { _id: 0, key: "$_id", doc_count: 1 } }, // 收集所有统计结果到buckets数组 { $group: { _id: null, buckets: { $push: "$$ROOT" } } }, // 整理为目标输出结构 { $project: { _id: 0, group_by_ram: { buckets: "$buckets" } } } ])
步骤说明
- 提取RAM值:通过
$filter筛选出specs数组中code为ram的条目,再用$map提取对应的value,$first确保单条记录只取一个RAM值(适配单设备单RAM规格的场景)。 - 过滤无效数据:剔除没有RAM规格的记录,避免干扰统计结果。
- 分组统计:按RAM值分组,用
$sum计算每个值的出现次数。 - 结构转换:把分组用的
_id转为要求的key字段,保留doc_count。 - 结果聚合:将所有统计条目收集到
buckets数组,最终包装成group_by_ram的结构。
适配多RAM条目场景
如果单条记录的specs中存在多个RAM条目(需去重),可将第一个$project阶段替换为:
{ $project: { ram_value: { $first: { $setUnion: { $map: { input: { $filter: { input: "$specs", cond: { $eq: ["$$this.code", "ram"] } } }, as: "spec", in: "$$spec.value" } } } } } }
用$setUnion对单条记录内的RAM值去重,再取第一个值参与统计。
内容的提问来源于stack exchange,提问作者user21471995
相关产品推荐
相关产品推荐

