使用MongoDB聚合框架统计数组相似元素——能否在$project阶段实现?
实现MongoDB聚合中$project阶段的答案统计需求
当然可以在$project阶段完成这个统计需求!MongoDB的聚合表达式(比如$reduce、$mergeObjects、$objectToArray等)能让我们直接在字段重塑阶段完成数组的计数和格式转换。下面针对你要的两种输出格式分别给出实现方案:
方案1:输出键值对对象格式
这个方案通过$reduce遍历answers数组累加计数,再用$mergeObjects动态更新计数对象:
db.collection.aggregate([ { $project: { result: { $reduce: { input: "$answers", initialValue: {}, in: { $mergeObjects: [ "$$value", { [$$current]: { $add: [ { $ifNull: ["$$value.$$current", 0] }, 1 ] } } ] } } }, _id: 0 // 隐藏_id字段,可选 } } ])
代码解释:
$reduce:遍历answers数组,initialValue初始化一个空对象作为计数容器$mergeObjects:每次遍历把当前的计数对象和新的键值对(当前选项+计数+1)合并$ifNull:处理首次出现的选项,避免因键不存在导致的计算错误,默认计数为0
方案2:输出二维数组格式
如果需要二维数组格式,可以在方案1的基础上用$objectToArray把计数对象转成二维数组:
db.collection.aggregate([ { $project: { result: { $objectToArray: { $reduce: { input: "$answers", initialValue: {}, in: { $mergeObjects: [ "$$value", { [$$current]: { $add: [ { $ifNull: ["$$value.$$current", 0] }, 1 ] } } ] } } } }, _id: 0 } } ])
额外说明:
如果你的需求是只统计multipleOptions中存在的选项(哪怕answers里没出现也显示0),可以稍微调整逻辑:先用$arrayToObject把multipleOptions转成初始计数为0的对象,再用$reduce更新计数,这样就能包含所有预设选项了。
比如针对第一个文档的multipleOptions,初始对象会是{"first":0,"second":0,"third":0,"forth":0},再遍历answers累加后得到完整的计数结果。
内容的提问来源于stack exchange,提问作者Milad ABC
相关产品推荐
相关产品推荐

