基于MongoDB聚合按类型和月份分组Media数据的技术问询
用MongoDB聚合管道实现按类型和月份分组的Media数据查询
完全可以通过MongoDB的聚合管道(aggregate)直接实现你要的分组格式,不需要在JS层额外处理。以下是具体的聚合方案:
聚合管道步骤
- 提取月份字段:将
date字符串转换为日期类型,再提取出月份数字。 - 按类型+月份分组:先把同类型同月份的文档归为一组,收集每组内的文档数据。
- 按类型二次分组:将同一类型下的不同月份数据整理成以月份为键的对象。
- 格式化最终结果:将分组后的结构转换为你期望的嵌套对象格式。
Mongoose代码实现
const groupedMedia = await Media.aggregate([ // 步骤1:提取月份 { $addFields: { month: { $month: { $dateFromString: { dateString: "$date" } } } } }, // 步骤2:按type和month分组,收集对应文档 { $group: { _id: { type: "$type", month: "$month" }, docs: { $push: "$$ROOT" } } }, // 步骤3:按type分组,将每个month的docs整理成键值对 { $group: { _id: "$_id.type", monthData: { $push: { k: { $toString: "$_id.month" }, v: "$docs" } } } }, // 步骤4:将monthData转换为对象,最终整理成目标格式 { $project: { _id: 0, typeData: { $arrayToObject: "$monthData" } } }, // 转换为最终的嵌套对象结构 { $group: { _id: null, result: { $arrayToObject: [{ k: "$_id", v: "$typeData" }] } } }, { $replaceRoot: { newRoot: "$result" } } ]); console.log(groupedMedia[0]);
代码说明
$dateFromString:将字符串格式的date字段转换为MongoDB可识别的日期类型,方便后续提取月份。$month:从日期中提取月份数字(1-12)。- 两次
$group:第一次按type+month分组收集文档,第二次按type将不同月份的分组结果聚合。 $arrayToObject:将数组格式的键值对转换为对象,实现你需要的{ 9: [...], 10: [...] }结构。$replaceRoot:将最终的聚合结果替换为根文档,得到你期望的嵌套对象格式。
这个聚合管道会直接从数据库返回符合要求的结构化数据,无需在应用层进行额外的分组处理。
内容的提问来源于stack exchange,提问作者Raphael Rlt
相关产品推荐
相关产品推荐

