MongoDB单查询实现物种统计与记录详情聚合需求
MongoDB聚合查询:按物种分组整合统计与详情记录
你可以通过MongoDB的聚合管道,结合$group、$arrayToObject和$replaceRoot等操作,实现单次查询完成分组统计、复用重复信息(比如亚科)并整合记录详情的需求,完全替代两次独立查询的方案。
完整聚合管道代码
db.yourCollectionName.aggregate([ // 第一步:按物种分组,统计数量、收集记录详情、提取亚科信息 { $group: { _id: "$Herbivore species", count: { $sum: 1 }, "Herbivore subfamily": { $first: "$Herbivore subfamily" }, records: { $push: { voucher: "$voucher", "Collection Date": "$Collection Date", Latitude: "$Latitude", Longitude: "$Longitude" } } } }, // 第二步:构造键值对数组,用于转换为以物种名为键的对象 { $project: { _id: 0, speciesEntry: { k: "$_id", v: { count: "$count", "Herbivore subfamily": "$Herbivore subfamily", records: "$records" } } } }, // 第三步:将键值对数组转换为对象 { $replaceRoot: { newRoot: { $arrayToObject: ["$speciesEntry"] } } }, // 第四步:将所有物种对象合并到一个数组中(匹配目标格式的外层数组) { $group: { _id: null, result: { $push: "$$ROOT" } } }, { $replaceRoot: { newRoot: "$result" } } ])
各阶段说明
$group阶段:
- 按
Herbivore species作为分组核心键(_id) - 用
$sum:1统计每个物种的记录总数 - 用
$first提取该物种的亚科信息(同一物种的亚科必然一致,取第一条即可复用,避免重复存储) - 用
$push将每条记录的核心字段(凭证号、采集日期、经纬度)收集到records数组中
- 按
$project阶段:
- 构造
speciesEntry字段,格式为{k: 物种名, v: {统计数据+亚科+记录详情}},为后续转换为目标结构做准备
- 构造
$replaceRoot + $arrayToObject阶段:
- 将键值对格式的
speciesEntry转换为以物种名为顶级键的对象,让结构贴合你期望的样式
- 将键值对格式的
最后两个$group + $replaceRoot阶段:
- 把所有独立的物种对象合并到一个外层数组中,和你给出的目标输出格式完全匹配
最终输出结果
执行后会得到你需要的结构:
[ { "Agrius cingulata": { "count": 1, "Herbivore subfamily": "Sphinginae", "records": [ { "voucher": "77-SRNP-4", "Collection Date": "1977-06-06T06:00:00.000Z", "Latitude": "10.83764", "Longitude": "-85.61871" } ] }, "Xylophanes turbata": { "count": 2, "Herbivore subfamily": "Macroglossinae", "records": [ { "voucher": "78-SRNP-10", "Collection Date": "1978-05-20T06:00:00.000Z", "Latitude": "10.80212", "Longitude": "-85.65372" }, { "voucher": "78-SRNP-10.02", "Collection Date": "1978-05-20T06:00:00.000Z", "Latitude": "10.80212", "Longitude": "-85.65372" } ] } } ]
这个方案只需要一次聚合查询,既复用了物种的亚科信息,又整合了统计数据和记录详情,有效降低了数据载荷。
内容的提问来源于stack exchange,提问作者wren
相关产品推荐
相关产品推荐

