Mongoose 聚合查询结果如何按年份、日双字段排序
问题根因
你当前排序结果不符合预期,本质是对嵌套对象的整体排序机制理解有偏差:MongoDB 对比嵌套对象做排序时,会按照_id内部定义的键顺序逐个值做对比。
你在$group阶段写的_id结构是先列day、再列year,所以排序时会优先比对day的大小,day值一致才会去比对year——这直接把需要的排序优先级搞反了,才会出现2021年2日、3日的记录排在2020年26日、27日前面的反常结果。
调整方案
前面的$match、$project、$group逻辑完全不用改动,只需要把原来直接排整个_id的配置,改成用点号明确指定排序字段的优先级即可:优先按年份升序,同一年份再按日升序。
将原有排序配置:
{ $sort: { _id: 1 } }
替换为:
{ $sort: { "_id.year": 1, "_id.day": 1 } }
调整后的完整聚合代码
MinutesSpentStudying.aggregate([ { $match: { connected_user_id: ObjectId(user_id) } }, { $project: { minutes_spent_studying: 1, year: { $year: "$date" }, day: { $dayOfMonth: "$date" }, }, }, { $group: { _id: { day: "$day", year: "$year", }, total_minutes: { $sum: "$minutes_spent_studying" }, }, }, // 替换原有的整体_id排序逻辑 { $sort: { "_id.year": 1, "_id.day": 1 } }, ]);
调整后效果
返回结果会完全匹配排序要求:
- 优先按年份升序排列,所有2020年的统计数据会排在2021年的记录之前
- 同一年份的记录再按日期的日维度升序排列
最终返回结构示例:
[ { "_id": { "day": 26, "year": 2020 }, "total_minutes": 1 }, { "_id": { "day": 27, "year": 2020 }, "total_minutes": 3 }, { "_id": { "day": 2, "year": 2021 }, "total_minutes": 11 }, { "_id": { "day": 3, "year": 2021 }, "total_minutes": 1 } ]
额外提示:如果调整
$group阶段的_id键顺序(把year放在day前面),虽然直接写{ $sort: { _id: 1 } }也能得到正确结果,但这种写法可读性差、可维护性弱,后续如果调整_id的键顺序很容易出现排序逻辑错误,更推荐前面用点号明确指定排序字段的写法。
内容的提问来源于stack exchange,提问作者AG_HIHI
相关产品推荐
相关产品推荐

