如何使用MongoDB aggregate实现用户多数组字段的批量计数
单次查询实现多数组字段统计方案
可以通过一次MongoDB聚合查询完成所有字段的统计需求,不需要重复发起多次请求,实现代码如下:
db.getCollection('users').aggregate([ // 收集所有文档对应数组字段的内容 { $group: { _id: null, fruits: { $push: { $ifNull: ["$fruits", []] } }, colors: { $push: { $ifNull: ["$colors", []] } }, habit: { $push: { $ifNull: ["$habit", []] } } } }, // 把每个字段收集到的二维数组合并为一维数组 { $project: { _id: 0, fruits: { $reduce: { input: "$fruits", initialValue: [], in: { $concatArrays: ["$$value", "$$this"] } } }, colors: { $reduce: { input: "$colors", initialValue: [], in: { $concatArrays: ["$$value", "$$this"] } } }, habit: { $reduce: { input: "$habit", initialValue: [], in: { $concatArrays: ["$$value", "$$this"] } } } } }, // 按要求格式生成统计结果 { $project: { fruits: { hasBanana: { $size: { $filter: { input: "$fruits", cond: { $eq: ["$$this", "banana"] } } } }, hasApple: { $size: { $filter: { input: "$fruits", cond: { $eq: ["$$this", "apple"] } } } }, hasPineapple: { $size: { $filter: { input: "$fruits", cond: { $eq: ["$$this", "pineapple"] } } } }, // 其他水果的统计项按相同规则补充即可 }, colors: { hasRed: { $size: { $filter: { input: "$colors", cond: { $eq: ["$$this", "red"] } } } }, hasBlue: { $size: { $filter: { input: "$colors", cond: { $eq: ["$$this", "blue"] } } } }, hasGreen: { $size: { $filter: { input: "$colors", cond: { $eq: ["$$this", "green"] } } } }, // 其他颜色的统计项按相同规则补充即可 }, habit: { hasRead: { $size: { $filter: { input: "$habit", cond: { $eq: ["$$this", "read"] } } } }, hasSing: { $size: { $filter: { input: "$habit", cond: { $eq: ["$$this", "sing"] } } } }, hasSleep: { $size: { $filter: { input: "$habit", cond: { $eq: ["$$this", "sleep"] } } } }, // 其他习惯的统计项按相同规则补充即可 } } } ])
如果不需要提前枚举要统计的元素,想要动态统计所有出现过的元素的次数,可以使用以下实现逻辑(以fruits字段为例,其他字段可同理扩展):
db.getCollection('users').aggregate([ { $unwind: "$fruits" }, { $group: { _id: "$fruits", count: { $sum: 1 } } }, { $group: { _id: null, fruits: { $push: { k: { $concat: ["has", { $toUpper: { $substrCP: ["$_id", 0, 1] } }, { $substrCP: ["$_id", 1, { $strLenCP: "$_id" }] }] }, v: "$count" } } } }, { $project: { _id: 0, fruits: { $arrayToObject: "$fruits" } } } ])
内容的提问来源于stack exchange,提问作者ripouu
相关产品推荐
相关产品推荐

