MongoDB聚合:如何将文档按指定大小分组为等窗口/块
按固定数量分块聚合MongoDB文档
这个需求其实挺常见的——要把文档按固定数量打包成chunk,而不是按字段值分组。咱们可以通过$setWindowFields配合分组操作来实现,核心思路是先给每个文档分配一个连续的序号,再根据序号计算它所属的分组,最后按分组聚合收集_id即可。
针对你的示例数据,这里给出可以直接运行的聚合查询:
db.coll.aggregate([ // 给每个文档添加连续行号,按_id排序保证顺序稳定 { $setWindowFields: { partitionBy: null, // 全局范围不分区 sortBy: { _id: 1 }, // 可根据业务需求替换其他排序字段 output: { rowNumber: { $rowNumber: {} } } } }, // 计算每个文档的分组键:每3个文档一组(实际替换为1024) { $set: { groupKey: { $floor: { $divide: [{ $subtract: ["$rowNumber", 1] }, 3] } } } }, // 按分组键聚合,收集对应组的_id到chunk中 { $group: { _id: "$groupKey", chunk: { $push: "$_id" } } }, // 可选:移除分组键的_id,只保留chunk字段 { $project: { _id: 0, chunk: 1 } } ])
关键步骤解释:
$setWindowFields阶段:这个阶段用来给每个文档生成唯一连续的行号。partitionBy: null表示对整个集合的文档进行编号,sortBy必须指定(否则行号顺序是不确定的),这里用_id排序是比较稳妥的选择,你也可以换成业务上需要的排序字段。- 计算
groupKey:通过$subtract把行号减1,再除以块大小(示例中是3)后取整,这样就能让每N个文档归为同一组——比如行号1-3会被分到groupKey=0,行号4-6分到groupKey=1,以此类推。 $group阶段:按groupKey分组,用$push把每组的_id收集到chunk数组里。- 可选的
$project阶段:如果你不需要结果中的分组标识,这个阶段可以移除_id字段,让输出完全符合你想要的格式。
把示例中的3替换成1024,就能满足你实际的块大小需求啦。
内容的提问来源于stack exchange,提问作者Andrii
相关产品推荐
相关产品推荐

