MongoDB聚合无需指定key统计details数组各字段值出现次数
MongoDB动态统计数组内字段值出现次数聚合方案
问题描述
在使用MongoDB聚合框架时,需要对数组返回的条目做count统计,但不希望在聚合逻辑中预先假设或使用对应的字段名。
示例数据结构
[ { "_id": "1", "title": "Vanella Icream", "contain": "sugar", "details": [ { "flavour": "Vanella" }, { "weight": "10KG" }, { "sugar": "15KG" } ] }, { "_id": "2", "title": "Pretzels", "contain": "salt", "details": [ { "flavour": "Wheat" }, { "weight": "10KG" }, { "sugar": "15KG" } ] }, { "_id": "3", "title": "Rasmalai Icream", "contain": "sugar", "details": [ { "flavour": "Vanella" }, { "weight": "15KG" }, { "sugar": "12KG" } ] }, { "_id": "4", "title": "Vanella Icream", "contain": "sugar", "details": [ { "flavour": "Vanella" }, { "weight": "15KG" }, { "sugar": "12KG" } ] } ]
期望输出结果
[ { "details": { "flavour": { "Vanella": 3, "Wheat": 1 }, "weight": { "10KG": 2, "15KG": 2 }, "sugar": { "12KG": 2, "15KG": 2 } } } ]
原实现痛点
原查询需要手动在$facet、$filter等阶段硬编码flavour、weight等字段名,无法适配details数组内字段动态增减的场景,即使details数组内有20个不同字段,也需要逐个添加对应处理逻辑。
动态适配聚合查询
以下方案无需预先指定details内的字段名,可自动识别所有字段并统计对应值的出现次数:
db.collection.aggregate([ // 拆分details数组得到每个子对象 { "$unwind": "$details" }, // 将每个details子对象转为键值对数组格式 { "$set": { "kvPairs": { "$objectToArray": "$details" } } }, // 拆分键值对数组,得到独立的键-值条目 { "$unwind": "$kvPairs" }, // 按键名+键值分组,统计每个值的出现次数 { "$group": { "_id": { "key": "$kvPairs.k", "value": "$kvPairs.v" }, "count": { "$sum": 1 } } }, // 按键名分组,收集同一键下所有值的统计结果 { "$group": { "_id": "$_id.key", "valueStats": { "$push": { "k": "$_id.value", "v": "$count" } } } }, // 聚合所有键的统计结果,转为顶层对象格式 { "$group": { "_id": null, "details": { "$push": { "k": "$_id", "v": { "$arrayToObject": "$valueStats" } } } } }, // 调整输出结构符合预期 { "$project": { "_id": 0, "details": { "$arrayToObject": "$details" } } } ])
内容的提问来源于stack exchange,提问作者Vishal Sharma
相关产品推荐
相关产品推荐

