You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Mongoose按日期分组数据并按pickups[0].time排序分组内容

需求说明

我的模型定义如下:

const scheduleTaskSchema = new Schema({
  activity: { type: Object, required: true },
  date: { type: Date, required: true },
  crew: Object,
  vehicle: Object,
  pickups: Array,
  details: String,
});

pickups是一个对象数组,结构如下:

{
  time : // ISO 格式日期,
  ...rest // 其他无关字段
}

我希望将数据按date字段分组返回,并且每个分组内的文档需要按照pickups[0].time进行排序,最终返回的数据结构如下例所示:

{
  "2022-08-28T00:00:00.000+00:00": [
    {
      date: "2022-08-28T00:00:00.000+00:00",
      pickups: [
        {
          time: "2022-08-28T07:30:00.000Z",
          ...rest // 其他无关字段
        }
      ],
      ...rest // 其他无关字段
    },
    {
      date: "2022-08-28T00:00:00.000+00:00",
      pickups: [
        {
          time: "2022-08-28T09:30:00.000Z",
          ...rest // 其他无关字段
        }
      ],
      ...rest // 其他无关字段
    }
  ],
  "2022-08-29T00:00:00.000+00:00": [
    {
      date: "2022-08-29T00:00:00.000+00:00",
      pickups: [
        {
          time: "2022-08-29T10:00:00.000Z",
          ...rest // 其他无关字段
        }
      ],
      ...rest // 其他无关字段
    },
    {
      date: "2022-08-29T00:00:00.000+00:00",
      pickups: [
        {
          time: "2022-08-29T11:30:00.000Z",
          ...rest // 其他无关字段
        }
      ],
      ...rest // 其他无关字段
    }
  ]
}
实现方案

可以通过MongoDB的聚合管道完成需求,具体操作如下:

  1. 添加排序字段:给每个文档新增sortTime字段,提取pickups数组第一个元素的time值,用于后续排序
  2. 按日期分组:将文档按date字段分组,同时收集组内所有文档
  3. 组内排序:对每个分组内的文档,按sortTime字段升序排序(降序可改为-1)
  4. 调整结果结构:移除不必要的字段,将分组结果转换为你需要的键值对格式

对应的聚合代码:

ScheduleTask.aggregate([
  // 添加排序用的sortTime字段
  {
    $addFields: {
      sortTime: { $arrayElemAt: ["$pickups.time", 0] }
    }
  },
  // 按date字段分组,收集组内文档
  {
    $group: {
      _id: "$date",
      docs: { $push: "$$ROOT" }
    }
  },
  // 对分组内的文档按sortTime升序排序
  {
    $addFields: {
      docs: {
        $sortArray: {
          input: "$docs",
          sortBy: { sortTime: 1 }
        }
      }
    }
  },
  // 移除sortTime字段,保留原始文档字段
  {
    $project: {
      _id: 0,
      dateKey: { $toString: "$_id" },
      docs: {
        $map: {
          input: "$docs",
          as: "doc",
          in: {
            activity: "$$doc.activity",
            date: "$$doc.date",
            crew: "$$doc.crew",
            vehicle: "$$doc.vehicle",
            pickups: "$$doc.pickups",
            details: "$$doc.details"
          }
        }
      }
    }
  },
  // 将分组结果合并为目标格式的对象
  {
    $group: {
      _id: null,
      result: {
        $mergeObjects: {
          $arrayToObject: [[{ k: "$dateKey", v: "$docs" }]]
        }
      }
    }
  },
  // 输出最终结果
  {
    $replaceRoot: { newRoot: "$result" }
  }
])
.then(result => {
  console.log(result);
})
.catch(err => {
  console.error(err);
});

兼容旧版本MongoDB(低于5.2)

如果你的MongoDB版本不支持$sortArray,可以用以下步骤替代排序环节:

// 替换原聚合中的排序步骤
{ $unwind: "$docs" },
{ $sort: { "docs.sortTime": 1 } },
{
  $group: {
    _id: "$_id",
    docs: { $push: "$docs" }
  }
},

内容的提问来源于stack exchange,提问作者Vaggelis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:01:02