【问题标题】:Aggregate query by Year and Month in MongoDB在 MongoDB 中按年和月聚合查询
【发布时间】:2022-01-14 06:33:00
【问题描述】:

我正在使用 MongoDB 4.2。

我有以下集合和聚合查询,用于在日期范围内按年和月返回计数。

[
  {
    "_id": ObjectId("60096afd7568e5a724966237"),
    "title": "One Hospitals",
    "createdAt": ISODate("2021-01-21T11:52:29.215Z")
  },
  {
    "_id": ObjectId("605492c632016f7bdd74c282"),
    "title": "Customer-5",
    "createdAt": ISODate("2021-07-19T12:02:14.134Z")
  },
  {
    "_id": ObjectId("60eeb32209434f1b24aff594"),
    "title": "UTR-007-HealthEndpoints",
    "createdAt": ISODate("2021-07-14T09:49:22.521Z")
  },
  {
    "_id": ObjectId("613a515cb24382575e7e766b"),
    "title": "UTR-004-005-Team",
    "createdAt": ISODate("2021-09-09T18:24:28.942Z")
  },
  {
    "_id": ObjectId("61605c5192467e75213a4374"),
    "title": "UTR-004-005-GC-Team",
    "createdAt": ISODate("2021-10-08T14:57:21.375Z")
  },
  {
    "_id": ObjectId("61826734c82e4e52c4663e1f"),
    "title": "Two Registry",
    "createdAt": ISODate("2021-11-03T10:40:52.611Z")
  },
  {
    "_id": ObjectId("61b090976a08dda345c15fb2"),
    "title": "Api Customer",
    "createdAt": ISODate("2021-12-08T11:01:43.011Z")
  }
]

聚合查询如下。

db.collection.aggregate([
  {
    $match: {
      $and: [
        {
          "createdAt": {
            $gte: ISODate("2021-07-01")
          }
        },
        {
          "createdAt": {
            $lte: ISODate("2021-12-31")
          }
        }
      ],
      
    }
  },
  {
    $group: {
      _id: {
        $dateToString: {
          "date": "$createdAt",
          "format": "%Y-%m"
        }
      },
      Count: {
        $sum: 1
      },
      
    }
  }
])

上述查询返回以下输出。

[
  {
    "Count": 1,
    "_id": "2021-09"
  },
  {
    "Count": 1,
    "_id": "2021-12"
  },
  {
    "Count": 1,
    "_id": "2021-11"
  },
  {
    "Count": 2,
    "_id": "2021-07"
  },
  {
    "Count": 1,
    "_id": "2021-10"
  }
]

谁能帮助实现以下目标?

  1. 输入文档没有 2021-08 的任何数据,因此在匹配组中提到的日期范围内添加 0 个缺失月份
  2. 添加一个名为 TITLE 且 MMM YYYY 的新字段(如 2021 年 7 月)
  3. 根据上面的_id对输出进行排序

总的来说,预期的输出应该如下。

[
  {
    "Count": 2,
    "_id": "2021-07",
    "Title": "Jul 2021"
  },
  {
    "Count": 0,
    "_id": "2021-08",
    "Title": "Aug 2021"
  },
  {
    "Count": 1,
    "_id": "2021-09",
    "Title": "Sep 2021"
  },
  {
    "Count": 1,
    "_id": "2021-10",
    "Title": "Oct 2021"
  },  {
    "Count": 1,
    "_id": "2021-11",
    "Title": "Nov 2021"
  },  
  {
    "Count": 1,
    "_id": "2021-12",
    "Title": "Dec 2021"
  }
]

我这里有MongoDB Playground 供您参考。

非常感谢您的帮助。

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    我建议升级到 Mongo 5.0,它提供了一些不错的功能,$dateTrunc$dateAdd$dateDiff 在这种情况下非常有用。如果您没有它们可用,那么您需要处理毫秒、$dateFromParts$dateToParts。但它需要更多代码。

    MongoDB 不支持本地化日期格式,例如月份名称。因此,您需要使用一些 JavaScript 库,例如moment.js

    或者您可以使用 $switch 构建月份名称的查找

    var ret = db.collection.aggregate([
       { $match: { createdAt: { $gte: ISODate("2021-07-01"), $lte: ISODate("2021-12-31") } } },
       {
          $group: {
             _id: { $dateTrunc: { date: "$createdAt", unit: "month" } },
             Count: { $count: {} }
          }
       },
       {
          $group: {
             _id: null,
             data: { $push: "$$ROOT" }
          }
       },
       {
          $set: {
             month: {
                $dateDiff: {
                   startDate: ISODate("2021-07-01"),
                   endDate: ISODate("2021-12-31"),
                   unit: "month"
                }
             }
          }
       },
       {
          $set: {
             data: {
                $map: {
                   input: { $range: [0, { $add: ["$month", 1] }] },
                   as: "m",
                   in: {
                      $let: {
                         vars: {
                            month: {
                               $dateAdd: {
                                  startDate: ISODate("2021-07-01"),
                                  unit: "month",
                                  amount: "$$m"
                               }
                            }
                         },
                         in: {
                            _id: "$$month",
                            Count: { $filter: { input: "$data", cond: { $eq: ["$$this._id", "$$month"] } } }
                         }
                      }
                   }
                }
             }
          }
       },
       {
          $set: {
             data: {
                $map: {
                   input: "$data",
                   in: { _id: "$$this._id", Count: { $ifNull: [{ $first: "$$this.Count.Count" }, 0] } }
                }
             }
          }
       },
       { $unwind: "$data" },
       { $replaceWith: "$data" },
       { $sort: { _id: 1 } }
    ]).toArray();
    
    ret.forEach(function (doc) { doc.Title = moment(doc._id).format('MMM YYYY') })
    print(tojsononeline(ret))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-01
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 2020-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多