MongoDB聚合:多字段去重分组并统计数量的实现
按品牌分组统计汽车文档(含去重逻辑)
嘿,我明白你的需求了——你有一组汽车文档,想要按make(品牌)分组,还得支持按make+model去重后再统计总数,最终输出成指定的makes数组格式。下面分两种场景给你解决方案,不管是用MongoDB处理数据库文档,还是前端纯JS数组都能搞定:
场景1:统计每个品牌的总文档数(不考虑车型重复)
如果你只是想统计每个品牌下的所有文档数量(比如Toyota的3条记录全部计入),用MongoDB的聚合框架可以这么写:
db.cars.aggregate([ // 第一步:按品牌分组,统计该品牌下的文档总数 { $group: { _id: "$make", total: { $sum: 1 } } }, // 第二步:把字段名改成你要的格式(_id转name,保留total) { $project: { _id: 0, name: "$_id", total: 1 } }, // 第三步:把所有品牌统计结果包装成makes数组 { $group: { _id: null, makes: { $push: "$$ROOT" } } }, // 最后去掉多余的_id字段 { $project: { _id: 0, makes: 1 } } ])
运行结果:
{ "makes": [ { "name": "Toyota", "total": 3 }, { "name": "Lexus", "total": 1 } ] }
场景2:统计每个品牌下的唯一车型数(先按品牌+车型去重)
如果你的需求是先去掉重复的品牌+车型组合,再统计每个品牌有多少种独特车型,调整一下聚合管道就行:
db.cars.aggregate([ // 第一步:先按品牌+车型去重,只保留唯一组合 { $group: { _id: { make: "$make", model: "$model" } } }, // 第二步:按品牌分组,统计该品牌下的唯一车型数量 { $group: { _id: "$_id.make", total: { $sum: 1 } } }, // 第三步:整理字段格式 { $project: { _id: 0, name: "$_id", total: 1 } }, // 第四步:包装成makes数组 { $group: { _id: null, makes: { $push: "$$ROOT" } } }, // 去掉多余的_id { $project: { _id: 0, makes: 1 } } ])
运行结果:
{ "makes": [ { "name": "Toyota", "total": 2 }, // Prius和Yaris两种独特车型 { "name": "Lexus", "total": 1 } ] }
纯JavaScript前端处理方案
如果你的数据是前端的JS数组,不用数据库,用reduce也能轻松实现:
场景1:统计品牌总文档数
const cars = [ { _id: 1, make: 'Toyota', model: 'Prius' }, { _id: 2, make: 'Toyota', model: 'Prius' }, { _id: 3, make: 'Toyota', model: 'Yaris' }, { _id: 4, make: 'Lexus', model: 'RX400' } ]; const result = cars.reduce((acc, car) => { // 找当前品牌是否已经在统计列表里 const existingBrand = acc.makes.find(item => item.name === car.make); if (existingBrand) { existingBrand.total += 1; } else { // 不在的话新增一条统计记录 acc.makes.push({ name: car.make, total: 1 }); } return acc; }, { makes: [] }); console.log(result);
场景2:统计品牌下的唯一车型数
const cars = [ { _id: 1, make: 'Toyota', model: 'Prius' }, { _id: 2, make: 'Toyota', model: 'Prius' }, { _id: 3, make: 'Toyota', model: 'Yaris' }, { _id: 4, make: 'Lexus', model: 'RX400' } ]; // 第一步:用Set去重品牌+车型组合 const uniqueModelPairs = [...new Set(cars.map(car => `${car.make}-${car.model}`))]; // 第二步:统计每个品牌的唯一车型数量 const result = uniqueModelPairs.reduce((acc, pair) => { const brand = pair.split('-')[0]; const existingBrand = acc.makes.find(item => item.name === brand); if (existingBrand) { existingBrand.total += 1; } else { acc.makes.push({ name: brand, total: 1 }); } return acc; }, { makes: [] }); console.log(result);
这样不管是数据库端还是前端,都能完美匹配你的需求啦~
内容的提问来源于stack exchange,提问作者Combustible Pizza
相关产品推荐
相关产品推荐

