MongoDB统计嵌套数组中各元素所在顶层文档数量
统计嵌套数组元素的顶层文档出现次数
需求:统计嵌套在数组型子文档的数组内的每个元素,分别存在于多少个顶层文档中,同一顶层文档内重复出现的元素仅计数一次。
文档示例
[{ "title": "fruit mix 1", "fruit_details": [ { "fruit_names": ["strawberry", "banana"], "category": "berries" }, { "fruit_names": ["strawberry", "apple", "mango"], "category": "red" } ] },{ "title": "fruit mix 2", "fruit_details": [ { "fruit_names": ["banana", "mango"], "category": "tropical" } ] },{ "title": "fruit mix 3", "fruit_details": [ { "fruit_names": ["banana", "lemon"], "category": "yellow" }, { "fruit_names": ["banana"], "category": "long" } ] }]
期望结果
[{ "_id": "banana", "count": 3 },{ "_id": "mango", "count": 2 },{ "_id": "lemon", "count": 1 },{ "_id": "strawberry", "count": 1 },{ "_id": "apple", "count": 1 }]
问题分析
你之前尝试的$setUnion用法有误,直接传入"$fruit_details.fruit_names"只会把多个fruit_names数组合并成数组集合,无法提取所有元素并在同一文档内去重,导致重复计数的问题。
正确聚合管道
db.collection.aggregate([ // 展开fruit_details数组,每个子文档成为独立条目 { $unwind: "$fruit_details" }, // 展开每个fruit_details下的fruit_names数组,每个水果名称成为独立条目 { $unwind: "$fruit_details.fruit_names" }, // 按顶层文档_id和水果名称分组,确保同一文档内同一水果只保留一条 { $group: { _id: { docId: "$_id", fruit: "$fruit_details.fruit_names" } } }, // 按水果名称分组,统计出现的不同文档数量 { $group: { _id: "$_id.fruit", count: { $sum: 1 } } }, // 按计数降序、名称升序排序(可选) { $sort: { count: -1, _id: 1 } } ])
步骤说明
- 两次$unwind:先拆
fruit_details数组,再拆fruit_names数组,把所有嵌套的水果名称提取成扁平化的条目。 - 第一次$group:以「顶层文档ID + 水果名称」为分组键,合并同一文档内重复的水果记录,确保每个文档每个水果仅保留一条。
- 第二次$group:以水果名称为分组键,统计对应的文档数量,得到该水果在多少个顶层文档中出现的次数。
- 排序:按计数降序、名称升序排列,让结果更直观。
内容的提问来源于stack exchange,提问作者Maximilian Carr
相关产品推荐
相关产品推荐

