如何用Mongoose按日期分组数据并按pickups[0].time排序分组内容
需求说明
我的模型定义如下:
const scheduleTaskSchema = new Schema({ activity: { type: Object, required: true }, date: { type: Date, required: true }, crew: Object, vehicle: Object, pickups: Array, details: String, });
pickups是一个对象数组,结构如下:
{ time : // ISO 格式日期, ...rest // 其他无关字段 }
我希望将数据按date字段分组返回,并且每个分组内的文档需要按照pickups[0].time进行排序,最终返回的数据结构如下例所示:
{ "2022-08-28T00:00:00.000+00:00": [ { date: "2022-08-28T00:00:00.000+00:00", pickups: [ { time: "2022-08-28T07:30:00.000Z", ...rest // 其他无关字段 } ], ...rest // 其他无关字段 }, { date: "2022-08-28T00:00:00.000+00:00", pickups: [ { time: "2022-08-28T09:30:00.000Z", ...rest // 其他无关字段 } ], ...rest // 其他无关字段 } ], "2022-08-29T00:00:00.000+00:00": [ { date: "2022-08-29T00:00:00.000+00:00", pickups: [ { time: "2022-08-29T10:00:00.000Z", ...rest // 其他无关字段 } ], ...rest // 其他无关字段 }, { date: "2022-08-29T00:00:00.000+00:00", pickups: [ { time: "2022-08-29T11:30:00.000Z", ...rest // 其他无关字段 } ], ...rest // 其他无关字段 } ] }
实现方案
可以通过MongoDB的聚合管道完成需求,具体操作如下:
- 添加排序字段:给每个文档新增
sortTime字段,提取pickups数组第一个元素的time值,用于后续排序 - 按日期分组:将文档按
date字段分组,同时收集组内所有文档 - 组内排序:对每个分组内的文档,按
sortTime字段升序排序(降序可改为-1) - 调整结果结构:移除不必要的字段,将分组结果转换为你需要的键值对格式
对应的聚合代码:
ScheduleTask.aggregate([ // 添加排序用的sortTime字段 { $addFields: { sortTime: { $arrayElemAt: ["$pickups.time", 0] } } }, // 按date字段分组,收集组内文档 { $group: { _id: "$date", docs: { $push: "$$ROOT" } } }, // 对分组内的文档按sortTime升序排序 { $addFields: { docs: { $sortArray: { input: "$docs", sortBy: { sortTime: 1 } } } } }, // 移除sortTime字段,保留原始文档字段 { $project: { _id: 0, dateKey: { $toString: "$_id" }, docs: { $map: { input: "$docs", as: "doc", in: { activity: "$$doc.activity", date: "$$doc.date", crew: "$$doc.crew", vehicle: "$$doc.vehicle", pickups: "$$doc.pickups", details: "$$doc.details" } } } } }, // 将分组结果合并为目标格式的对象 { $group: { _id: null, result: { $mergeObjects: { $arrayToObject: [[{ k: "$dateKey", v: "$docs" }]] } } } }, // 输出最终结果 { $replaceRoot: { newRoot: "$result" } } ]) .then(result => { console.log(result); }) .catch(err => { console.error(err); });
兼容旧版本MongoDB(低于5.2)
如果你的MongoDB版本不支持$sortArray,可以用以下步骤替代排序环节:
// 替换原聚合中的排序步骤 { $unwind: "$docs" }, { $sort: { "docs.sortTime": 1 } }, { $group: { _id: "$_id", docs: { $push: "$docs" } } },
内容的提问来源于stack exchange,提问作者Vaggelis
相关产品推荐
相关产品推荐

