MongoDB技术问询:按object1分组统计选中与未选中对象出现次数
MongoDB聚合管道:按Object1统计选中/未选中次数
以下是实现需求的两种聚合管道方案,均能输出你期望的格式:
方案一:使用$facet并行统计(高效推荐)
这个方案通过$facet同时完成三类统计,避免多次遍历集合,性能更优:
db.your_collection_name.aggregate([ // 1. 并行执行三个分组操作,分别统计选中次数、未选中次数,以及收集所有Object1的唯一值 { $facet: { "selected_counts": [ { $group: { _id: "$selected", // 替换为你实际的selected字段名,比如$selectedObject selected_count: { $sum: 1 } } } ], "unselected_counts": [ { $group: { _id: "$Unselected", // 替换为你实际的unselected字段名,比如$unselectedObject unselected_count: { $sum: 1 } } } ], "object1_objects": [ { $group: { _id: "$Object1" // 替换为你实际的object1字段名,比如$object1 } } ] } }, // 2. 将Object1的唯一值数组拆分为单个文档 { $unwind: "$object1_objects" }, // 3. 重命名字段为输出需要的格式 { $project: { Object: "$object1_objects._id", selected_counts: 1, unselected_counts: 1 } }, // 4. 匹配当前Object对应的选中次数,无匹配则设为0 { $addFields: { Selected: { $let: { vars: { matched: { $first: { $filter: { input: "$selected_counts", cond: { $eq: ["$$this._id", "$Object"] } } } } }, in: { $ifNull: ["$$matched.selected_count", 0] } } } } }, // 5. 匹配当前Object对应的未选中次数,无匹配则设为0 { $addFields: { Unselected: { $let: { vars: { matched: { $first: { $filter: { input: "$unselected_counts", cond: { $eq: ["$$this._id", "$Object"] } } } } }, in: { $ifNull: ["$$matched.unselected_count", 0] } } } } }, // 6. 保留需要的输出字段,移除默认_id { $project: { _id: 0, Object: 1, Selected: 1, Unselected: 1 } } ])
关键阶段说明
$facet:一次性完成三类统计任务,减少集合遍历次数;$filter+$ifNull:实现统计数据的匹配与默认值填充,确保未出现的对象计数为0;- 最后一步
$project:严格对齐期望的输出字段格式。
方案二:拆分文档后统计
这个方案通过拆分每个文档为选中、未选中两条记录,再统一统计:
db.your_collection_name.aggregate([ // 1. 将每个文档拆分为两条记录,分别标记选中/未选中类型 { $unionWith: { coll: "your_collection_name", // 替换为你的集合名 pipeline: [ { $project: { obj: "$selected", type: "selected", object1: "$Object1" } }, { $project: { obj: "$Unselected", type: "unselected", object1: "$Object1" } } ] } }, // 2. 收集所有Object1的唯一值及所有拆分后的记录 { $group: { _id: null, object1_list: { $addToSet: "$object1" }, all_records: { $push: "$$ROOT" } } }, // 3. 遍历每个Object1对象,统计对应选中/未选中次数 { $unwind: "$object1_list" }, { $project: { Object: "$object1_list", Selected: { $size: { $filter: { input: "$all_records", cond: { $and: [{ $eq: ["$$this.obj", "$object1_list"] }, { $eq: ["$$this.type", "selected"] }] } } } }, Unselected: { $size: { $filter: { input: "$all_records", cond: { $and: [{ $eq: ["$$this.obj", "$object1_list"] }, { $eq: ["$$this.type", "unselected"] }] } } } } } }, // 4. 移除默认_id { $project: { _id: 0 } } ])
注意事项
- 请将代码中的
your_collection_name替换为你的实际集合名称; - 字段名需与你集合中的实际字段对齐:比如示例中的
selected/Unselected/Object1,如果你的集合是selectedObject/unselectedObject/object1,请对应修改代码中的字段引用。
内容的提问来源于stack exchange,提问作者Kyle Desmond
相关产品推荐
相关产品推荐

