MongoDB聚合查询:按产品及版本层级分组文档
用MongoDB聚合实现产品-版本的层级分组查询
嘿,刚好我之前做过类似的需求,用MongoDB的聚合管道完全能实现你想要的这种层级式分组结果,下面给你拆解具体的实现步骤和完整代码:
核心思路
我们需要通过两次$group分组先聚合版本数据,再聚合产品数据,最后用$arrayToObject和$replaceRoot把分组结果转换成你要的键值对层级结构。
第一步:按「产品+版本」分组收集文档
这一步先把相同产品相同版本的所有文档归到一组,把组内的文档都存进一个数组里:
{ $group: { _id: { product: "$product", version: "$version" }, docs: { $push: "$$ROOT" } // 把当前组的所有原始文档推送到docs数组中 } }
第二步:按「产品」分组整合版本数据
现在把同一个产品下的不同版本组整合起来,这里要把每个版本对应的文档数组转换成{k: 版本号, v: 文档数组}的格式,方便后续转成对象:
{ $group: { _id: "$_id.product", versions: { $push: { k: "$_id.version", v: "$docs" } } } }
第三步:转换为目标层级结构
用$arrayToObject把版本数组转成以版本号为键的对象,再用$replaceRoot把整个文档替换成以产品名为键的最终结构:
{ $replaceRoot: { newRoot: { $arrayToObject: [[{ k: "$_id", v: { $arrayToObject: "$versions" } }]] } } }
完整聚合查询代码
把上面三个阶段组合起来,完整的查询语句如下:
db.collection.aggregate([ // 可选:如果需要把字符串格式的created转成Date类型,添加这个阶段 // { // $addFields: { // created: { $toDate: "$created" } // } // }, // 第一步:按产品+版本分组 { $group: { _id: { product: "$product", version: "$version" }, docs: { $push: "$$ROOT" } } }, // 第二步:按产品分组整合版本数据 { $group: { _id: "$_id.product", versions: { $push: { k: "$_id.version", v: "$docs" } } } }, // 第三步:转换为目标层级结构 { $replaceRoot: { newRoot: { $arrayToObject: [[{ k: "$_id", v: { $arrayToObject: "$versions" } }]] } } } ])
最终结果示例
执行这个查询后,你会得到完全符合需求的结构:
{ "product1": { "1.0": [ {"product": "product1", "version": "1.0", ...}, {"product": "product1", "version": "1.0", ...} ], "1.5": [ {"product": "product1", "version": "1.5", ...} ] }, "product2": { "2.0": [ {"product": "product2", "version": "2.0", ...} ] } }
另外提个小建议:如果你的created字段是字符串格式,后续要是需要按时间排序或者做时间相关的聚合,可以在最前面加上注释里的$addFields阶段,把它转换成标准的Date类型,这样后续操作会更方便。
内容的提问来源于stack exchange,提问作者ProperBritish
相关产品推荐
相关产品推荐

