MongoDB嵌套数组按Filter的name和value分组统计实现方案
嘿,这需求我熟!咱们分两种输出格式来一步步实现,都是用MongoDB的聚合管道搞定👇
实现第二种输出格式(扁平结构)
这种格式是最直观的统计结果,每个条目对应一个filter name + value的组合和计数。
聚合代码
db.collection.aggregate([ // 展开variants数组,让每个变体单独成为一个文档 { $unwind: "$variants" }, // 再展开每个变体下的filters数组,让每个filter单独成为一个文档 { $unwind: "$variants.filters" }, // 按filter的name和value组合分组,统计数量 { $group: { _id: { filterName: "$variants.filters.name", filterValue: "$variants.filters.value" }, count: { $sum: 1 } } }, // 整理成你要的输出字段格式,去掉默认的_id { $project: { _id: 0, name: "$_id.filterName", value: "$_id.filterValue", count: 1 } } ])
关键步骤说明
- 两次
$unwind是为了把嵌套的数组完全拆平,确保每个filter都能被单独统计。 $group用复合键(filterName + filterValue)作为分组依据,保证每个不同的组合都能得到独立的计数。$project负责把分组后的字段重命名成你需要的格式,同时移除不需要的_id字段。
实现第一种输出格式(嵌套键值结构)
这种格式把同一个filter name的所有value统计结果聚合在一起,用filter name作为键。
聚合代码
db.collection.aggregate([ // 同样先拆平嵌套的数组 { $unwind: "$variants" }, { $unwind: "$variants.filters" }, // 第一步分组:统计每个name-value组合的数量 { $group: { _id: { filterName: "$variants.filters.name", filterValue: "$variants.filters.value" }, count: { $sum: 1 } } }, // 第二步分组:按filter name聚合,收集对应的value和计数数组 { $group: { _id: "$_id.filterName", values: { $push: { value: "$_id.filterValue", count: "$count" } } } }, // 把filter name转换为对象的键,values数组作为对应的值 { $project: { _id: 0, filterEntry: { $arrayToObject: [[{ k: "$_id", v: "$values" }]] } } }, // 把每个filterEntry对象作为根文档输出 { $replaceRoot: { newRoot: "$filterEntry" } } ])
关键步骤说明
- 前两步和扁平结构一致,先拆平数组并统计基础的name-value计数。
- 第二次
$group是核心:把同一个filter name下的所有value-count组合收集成一个数组。 $arrayToObject用来将filter name动态转换成对象的键,实现你要的嵌套结构。$replaceRoot把转换后的对象作为输出的根文档,最终得到你期望的数组格式。
内容的提问来源于stack exchange,提问作者Mihir Shah
相关产品推荐
相关产品推荐

