MongoDB聚合查询闰年结果错误,寻求修正方案
问题:MongoDB聚合统计闰年结果异常
文档数据
{ "_id" : ObjectId("63a994974ac549c5ea982d2b"), "title" : "Destroyer", "year" : 2018 }, { "_id" : ObjectId("63a994974ac549c5ea982d2a"), "title" : "Aquaman", "year" : 2014 }, { "_id" : ObjectId("63a994974ac549c5ea982d29"), "title" : "On the Basis of Sex", "year" : 1996 }, { "_id" : ObjectId("63a994974ac549c5ea982d28"), "title" : "Holmes and Watson", "year" : 1940 }, { "_id" : ObjectId("63a994974ac549c5ea982d27"), "title" : "Conundrum: Secrets Among Friends", "year" : 1957 }, { "_id" : ObjectId("63a994974ac549c5ea982d26"), "title" : "Welcome to Marwen", "year" : 2004 }, { "_id" : ObjectId("63a994974ac549c5ea982d25"), "title" : "Mary Poppins Returns", "year" : 1997 }, { "_id" : ObjectId("63a994974ac549c5ea982d24"), "title" : "Bumblebee", "year" : 2004 }
错误的聚合管道代码
var query0 = {$group: {"_id": {"year": "$year"}}} var query1 = {$addFields: { leap: { "$and": [ {"$eq": [{"$mod": ["$year",4]}, 0]}, {"$or": [ {"$ne": [{"$mod": ["$year", 100]}, 0]}, {"$eq": [{"$mod": ["$year", 400]}, 0] } ]} ] } }} var query2 = {$project: {leap: true}} var query3 = {$group: { "_id": "$leap", "count": {$sum: 1} }} var etapas = [query0, query1, query2, query3] db.genres.aggregate(etapas)
实际输出
{ "_id": false, "count": 8 }
期望输出
{ "_id": "Leap", "count": 3 }
问题原因与修正方案
问题1:字段引用错误
第一个$group阶段执行后,所有年份字段被嵌套在_id.year结构下,但后续$addFields中仍直接用$year引用,导致MongoDB无法找到目标字段,最终所有leap计算结果为false,统计出全为非闰年的错误结果。
问题2:输出格式不匹配
原代码按布尔值true/false分组,而期望输出_id为字符串"Leap",需要将布尔值映射为对应文本。
修正后的聚合管道
var query0 = {$group: {"_id": {"year": "$year"}}} var query1 = {$addFields: { leap: { "$and": [ {"$eq": [{"$mod": ["$_id.year",4]}, 0]}, {"$or": [ {"$ne": [{"$mod": ["$_id.year", 100]}, 0]}, {"$eq": [{"$mod": ["$_id.year", 400]}, 0] } ]} ] } }} var query2 = {$project: {leap: true}} var query3 = {$group: { "_id": {$cond: ["$leap", "Leap", "Non-Leap"]}, "count": {$sum: 1} }} // 可选:仅保留闰年统计结果,不需要则移除该阶段 var query4 = {$match: {"_id": "Leap"}} var etapas = [query0, query1, query2, query3, query4] db.genres.aggregate(etapas)
说明
- 将
$addFields中的$year全部替换为$_id.year,确保正确获取分组后的年份值。 - 在最后一个
$group阶段用$cond将布尔值映射为字符串,匹配期望的输出格式。 - 新增的
$match阶段可过滤非闰年数据,若需要同时展示两种结果,直接移除该阶段即可。
执行修正后的代码,将得到期望输出:
{ "_id": "Leap", "count": 3 }
内容的提问来源于stack exchange,提问作者DatBigD
相关产品推荐
相关产品推荐

