MongoDB按条件分组:如何统计包含虚拟逾期状态的各类型任务数量
解决方案
可以通过MongoDB聚合管道的动态字段计算能力实现需求,无需修改原有Schema,具体实现如下:
核心思路
- 先通过
$addFields阶段动态生成计算后的统计状态,包含Overdue的判断逻辑 - 再按状态、任务类型两级分组统计数量
- 最后格式化输出为要求的结构,补全数量为0的类型
完整实现代码
const Task = mongoose.model('Task', taskSchema); const currentTime = new Date(); // 定义所有需要统计的任务类型,用于后续补全0值 const ALL_TYPES = ['Call Back', 'Visit', 'Meet', 'Site']; // 定义所有需要统计的状态 const ALL_STATUS = ['Pending', 'Completed', 'Overdue']; const stats = await Task.aggregate([ // 第一步:动态计算统计用的状态 { $addFields: { statsStatus: { $cond: { if: { $and: [ { $eq: ['$status', 'Pending'] }, { $lt: ['$due_date', currentTime] }, // 排除due_date为空的场景 { $ne: ['$due_date', null] }, { $ne: ['$due_date', ''] } ] }, then: 'Overdue', else: '$status' } } } }, // 第二步:按统计状态+任务类型分组计数 { $group: { _id: { status: '$statsStatus', type: '$type' }, count: { $sum: 1 } } }, // 第三步:按状态聚合,把同状态下的所有类型计数拼成对象 { $group: { _id: '$_id.status', typeCounts: { $push: { k: '$_id.type', v: '$count' } } } }, // 第四步:转成要求的键值结构 { $replaceRoot: { newRoot: { $arrayToObject: [[ { k: '$_id', v: { $arrayToObject: '$typeCounts' } } ]] } } } ]); // 补全所有状态和类型的默认0值(聚合只会返回有数据的条目,缺失的需要手动补) const result = Object.assign({}, ...stats); ALL_STATUS.forEach(status => { if (!result[status]) result[status] = {}; ALL_TYPES.forEach(type => { if (result[status][type] === undefined) { result[status][type] = 0; } }); });
执行完上述代码后,result就是你要求的输出格式。
内容的提问来源于stack exchange,提问作者Uday Mittal
相关产品推荐
相关产品推荐

