You need to enable JavaScript to run this app. Mongoose 聚合查询结果如何按年份、日双字段排序
优惠活动
大模型
产品
解决方案
定价
更多

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 } },
]);

调整后效果

返回结果会完全匹配排序要求:

  1. 优先按年份升序排列,所有2020年的统计数据会排在2021年的记录之前
  2. 同一年份的记录再按日期的日维度升序排列
    最终返回结构示例:
[
  {
      "_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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.08 21:54:05