MongoDB单请求实现城市与公司分组的Top N统计需求
MongoDB 单次聚合获取Top N热门城市与公司统计方案
解决全表扫描问题:先建索引
要避免聚合时的全表扫描,先为city和company字段创建复合索引,让MongoDB能利用索引快速完成分组统计:
db.employees.createIndex({ city: 1, company: 1 })
如果后续只侧重其中一个维度的统计,也可以单独建单字段索引(比如{city:1}或{company:1}),复合索引则能同时满足两个维度的统计需求。
单次请求实现双维度Top N统计
使用$facet聚合操作,可以在单次请求中并行处理城市和公司两个维度的统计逻辑,最终输出符合要求的格式。以下是完整聚合管道代码(将4替换为你需要的Top N数值):
db.employees.aggregate([ // 分两个并行管道处理城市和公司统计 { $facet: { topCities: [ { $group: { _id: "$city", count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 4 }, // 将分组结果转换为{城市名: 数量}的格式 { $replaceRoot: { newRoot: { $arrayToObject: [[{ k: "$_id", v: "$count" }]] } } } ], topCompanies: [ { $group: { _id: "$company", count: { $sum: 1 } } }, { $sort: { count: -1 } }, { $limit: 4 }, // 将分组结果转换为{公司名: 数量}的格式 { $replaceRoot: { newRoot: { $arrayToObject: [[{ k: "$_id", v: "$count" }]] } } } ] } }, // 合并两个管道的结果为一个数组 { $project: { result: { $concatArrays: ["$topCities", "$topCompanies"] } } }, // 将合并后的数组作为最终输出 { $replaceRoot: { newRoot: "$result" } } ])
代码逻辑说明
$facet:允许在一次聚合中运行多个独立的管道分支,分别生成城市和公司的统计结果,避免多次请求数据库。$group:按city/company字段分组,用$sum:1统计每组的员工数量。$sort + $limit:按统计数量倒序排序后保留前N个结果,过滤掉非热门分组,减少后续数据处理量。$arrayToObject + $replaceRoot:将分组后的_id(城市/公司名称)转换为对象的键,count转换为对应的值,完全匹配你需要的输出格式。$concatArrays:将城市和公司的统计结果数组合并,最终输出一个包含两个对象的数组。
内容的提问来源于stack exchange,提问作者Pono
相关产品推荐
相关产品推荐

