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

MongoDB嵌套数组按日期分组过滤查询需求

MongoDB按日期分组逾期预约解决方案

早上好!针对你提到的需求——查询所有逾期预约并按日期分组,我来一步步帮你梳理:

原始文档结构

你的MongoDB文档结构如下:

{
  "company": "ESPIRAL",
  "osServico": [
    {
      "_id": ObjectId("5afdbb931e511b23b621ff93"),
      "atend": [
        {
          "aut": null,
          "_id": ObjectId("5afdc1369d845d25c5196044"),
          "tec": ObjectId("5af18fa5a0d18a0320149de4"),
          "data": ISODate("2018-05-16T00:00:00.000Z")
        },
        {
          "aut": null,
          "_id": ObjectId("5afdc74a58f31a284d8d4d4f"),
          "tec": ObjectId("5af18fa5a0d18a0320149de4"),
          "data": ISODate("2018-05-16T00:00:00.000Z")
        },
        {
          "aut": null,
          "_id": ObjectId("5afdc7b577ee6b28948137a8"),
          "tec": ObjectId("5ad9fdea68ab9f0014ddb5d2"),
          "data": ISODate("2018-05-15T00:00:00.000Z")
        }
      ]
    }
  ]
}

期望的分组结果

你希望得到按日期拆分后的结果,每个日期对应一组逾期记录:

[
  {
    "company": "ESPIRAL",
    "osServico": [
      {
        "_id": ObjectId("5afdbb931e511b23b621ff93"),
        "atend": [
          {
            "aut": null,
            "_id": ObjectId("5afdc7b577ee6b28948137a8"),
            "tec": ObjectId("5ad9fdea68ab9f0014ddb5d2"),
            "data": ISODate("2018-05-15T00:00:00.000Z")
          }
        ]
      }
    ]
  },
  {
    "company": "ESPIRAL",
    "osServico": [
      {
        "_id": ObjectId("5afdbb931e511b23b621ff93"),
        "atend": [
          {
            "aut": null,
            "_id": ObjectId("5afdc1369d845d25c5196044"),
            "tec": ObjectId("5af18fa5a0d18a0320149de4"),
            "data": ISODate("2018-05-16T00:00:00.000Z")
          },
          {
            "aut": null,
            "_id": ObjectId("5afdc74a58f31a284d8d4d4f"),
            "tec": ObjectId("5af18fa5a0d18a0320149de4"),
            "data": ISODate("2018-05-16T00:00:00.000Z")
          }
        ]
      }
    ]
  }
]

现有查询的问题

你当前的查询能过滤出逾期的atend记录,但缺少分组的核心步骤,所以无法按日期拆分结果:

[
  {
    $match: { "osServico.atend.data": { $lt: data } }
  },
  {
    $addFields: {
      "osServico": {
        "$map": {
          "input": "$osServico",
          "as": "os",
          "in": {
            "_id": "$$os._id",
            "servico": "$$os.servico",
            "atend": {
              "$filter": {
                "input": "$$os.atend",
                "as": "atend",
                "cond": { $and: [{ $lt: ["$$atend.data", data] }] }
              }
            }
          }
        }
      }
    }
  }
]

完整的聚合解决方案

要实现按日期分组,我们需要用$unwind展开嵌套数组,再用$group按日期聚合,最后重新构建文档结构,完整的聚合管道如下:

[
  // 第一步:匹配包含逾期记录的文档(先缩小处理范围)
  { $match: { "osServico.atend.data": { $lt: data } } },
  // 第二步:展开osServico数组,单独处理每个服务项
  { $unwind: "$osServico" },
  // 第三步:展开每个服务项下的atend数组,单独处理每条预约记录
  { $unwind: "$osServico.atend" },
  // 第四步:过滤出单条逾期的预约记录(确保只保留符合条件的项)
  { $match: { "osServico.atend.data": { $lt: data } } },
  // 第五步:按日期+公司+服务ID分组,聚合同日期的逾期记录
  {
    $group: {
      _id: {
        date: "$osServico.atend.data",
        company: "$company",
        osId: "$osServico._id"
      },
      atendList: { $push: "$osServico.atend" }
    }
  },
  // 第六步:重新构建成你期望的文档格式
  {
    $project: {
      _id: 0,
      company: "$_id.company",
      osServico: [
        {
          _id: "$_id.osId",
          atend: "$atendList"
        }
      ]
    }
  }
]

关键步骤说明:

  • $unwind:把嵌套的osServico和atend数组依次拆成单条文档,让每个预约记录都成为独立的处理单元,这是分组的前提。
  • $group:以日期、公司、服务项ID为分组键,把同日期的所有逾期预约聚合到一个列表中,保证同一日期的记录会被归为一组。
  • $project:重新整理输出结构,和你期望的格式完全对齐。

这样就能得到按日期分组的逾期预约结果啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:27:56