在 MongoDB 中按年和月聚合查询
Posted
技术标签:
【中文标题】在 MongoDB 中按年和月聚合查询【英文标题】:Aggregate query by Year and Month in 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"
]
谁能帮助实现以下目标?
-
输入文档没有 2021-08 的任何数据,因此在匹配组中提到的日期范围内添加 0 个缺失月份
添加一个名为 TITLE 且 MMM YYYY 的新字段(如 2021 年 7 月)
根据上面的_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 供您参考。
非常感谢您的帮助。
【问题讨论】:
【参考方案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))
【讨论】:
以上是关于在 MongoDB 中按年和月聚合查询的主要内容,如果未能解决你的问题,请参考以下文章
我需要从结构为 yyyyMMddHHmmss 20170227141500 的时间戳中按年和月分组
如何在oracle sql developer中按年和月分组获取当前财政年度的数据?