MongoDB聚合查询需求:统计数组内自由文本响应的出现次数
解决MongoDB文档新增freeTextResponses统计字段的需求
没问题,我来帮你搞定这个需求!咱们可以通过MongoDB的聚合管道来实现,核心思路是先拆分数组统计频次,再把统计结果转换成你要的格式,最后合并回原文档。
完整聚合查询语句
db.your_collection_name.aggregate([ // 第一步:定位到目标文档(替换成你的文档_id或者其他查询条件) { $match: { _id: ObjectId("5a4c7eedb1016444df846a24") } }, // 第二步:拆分optionsAll数组,让每个子文档单独成为一条记录 { $unwind: "$optionsAll" }, // 第三步:按freeTextResponse内容分组,统计出现次数 { $group: { _id: "$optionsAll.freeTextResponse", count: { $sum: 1 } } }, // 第四步:把统计结果转换成要求的嵌套数组格式,同时把次数转成浮点数 { $project: { _id: 0, responseEntry: [ { $toDouble: "$count" }, { freeTextResponse: "$_id" } ] } }, // 第五步:把所有统计条目收集成一个数组,命名为freeTextResponses { $group: { _id: null, freeTextResponses: { $push: "$responseEntry" } } }, // 第六步:关联回原文档,获取其他原始字段 { $lookup: { from: "your_collection_name", localField: "_id", foreignField: "_id", as: "originalDoc" } }, // 第七步:展开原文档数组,合并字段 { $unwind: "$originalDoc" }, // 第八步:整合所有字段,保留原文档内容和新增的统计字段 { $project: { _id: "$originalDoc._id", questionText: "$originalDoc.questionText", questionType: "$originalDoc.questionType", optionsAll: "$originalDoc.optionsAll", optionsUnique: "$originalDoc.optionsUnique", activityId: "$originalDoc.activityId", freeTextResponses: 1 } }, // 第九步:把结果合并回原集合(如果只是查询可以去掉这一步,直接看结果) { $merge: { into: "your_collection_name", on: "_id", whenMatched: "replace", whenNotMatched: "discard" } } ])
关键步骤解释
- $unwind:把
optionsAll数组拆分成单个文档,这样才能对每个freeTextResponse进行单独统计。 - $group(第一次):按
freeTextResponse的内容分组,用$sum:1统计出现次数。 - $project:这里把统计结果转换成你需要的
[次数, {内容}]格式,用$toDouble把整数次数转成浮点数(比如2→2.0),完全匹配你给的示例格式。 - $lookup + $unwind:这两步是为了把统计好的
freeTextResponses数组和原文档的其他字段合并在一起,避免丢失原始数据。 - $merge:如果需要永久修改原文档,加上这一步就会把新增字段更新回集合;如果只是临时查询结果,去掉这一步即可。
注意事项
- 记得把语句里的
your_collection_name替换成你实际的集合名称。 - 如果需要批量处理多个文档,只需要修改
$match阶段的条件(比如去掉_id匹配,换成匹配所有需要处理的文档)。
内容的提问来源于stack exchange,提问作者Beginner
相关产品推荐
相关产品推荐

