MongoDB如何分组不同键的值并统计0/0、0/1的出现次数?
解决MongoDB动态键分组及0/0、0/1次数统计问题
没问题,这种动态键的分组统计确实有点 tricky,但MongoDB的聚合管道完全能搞定!先假设你的文档结构大概是这样的(方便后续演示):
{ "_id": ObjectId("60d21b4667d0d8992e610c85"), "samples": { "sensor_202": [0, 0], "sensor_317": [0, 1], "sensor_459": [1, 0], "sensor_108": [0, 0] } }
下面是针对这个场景的聚合方案,我会一步步拆解每个阶段的作用:
完整聚合管道命令
db.yourCollection.aggregate([ // 第一步:把samples对象转成键值对数组,统一处理动态键 { $addFields: { sampleEntries: { $objectToArray: "$samples" } } }, // 第二步:展开数组,让每个键值对成为独立文档 { $unwind: "$sampleEntries" }, // 第三步:提取值数组的两个元素,拼接成我们要统计的模式(比如"0/0") { $addFields: { pattern: { $concat: [ { $toString: { $arrayElemAt: ["$sampleEntries.v", 0] } }, "/", { $toString: { $arrayElemAt: ["$sampleEntries.v", 1] } } ] } } }, // 第四步:按模式分组,统计出现次数 { $group: { _id: "$pattern", count: { $sum: 1 } } }, // 可选:只保留你关心的0/0、0/1模式,过滤掉其他 { $match: { _id: { $in: ["0/0", "0/1"] } } }, // 可选:重命名_id为pattern,让结果更直观 { $project: { _id: 0, pattern: "$_id", count: 1 } } ])
各阶段详细解释
- $addFields + $objectToArray:这是处理动态键的核心!
$objectToArray会把samples这样的对象转换成[{k: "键名", v: "对应值"}]的数组,不管你的键叫什么,都能统一处理。 - $unwind:把上面生成的数组展开,每个键值对单独成为一条文档,这样我们就能逐个处理每个键对应的值。
- $addFields + $concat:从值数组(比如
[0,0])里提取第一个和第二个元素,转成字符串后用/拼接成"0/0"这样的模式,方便后续分组统计。 - $group:按拼接好的
pattern分组,用$sum:1统计每个模式出现的总次数。 - $match(可选):如果你只关心
0/0和0/1,可以用这个阶段过滤掉其他模式的结果。 - $project(可选):把默认的
_id字段重命名为pattern,让最终结果的可读性更好。
注意事项
- 如果你的
samples里存在值不是长度为2的数组的情况(比如空数组、单元素数组),可以在$unwind之后加一个$match阶段过滤掉这些异常数据:{ $match: { $expr: { $eq: [{ $size: "$sampleEntries.v" }, 2] } } } - 记得把
db.yourCollection替换成你实际的集合名称哦!
内容的提问来源于stack exchange,提问作者Crabime
相关产品推荐
相关产品推荐

