我正在使用 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"
}
]
任何人都可以帮助实现以下目标吗?
总的来说,预期的输出应该如下。
[
{
"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供您参考。
非常感谢您的帮助。
我建议升级到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))
$lte
或$lt
在日期过滤方面存在一些问题,我所做的是:$gte: "your date"
这就是解决这个问题的方法
{
$and: [
{
date: {
$gt: "Sun Jan 01 2023 05:00:00 GMT+0500 (Pakistan Standard Time)",
},
},
{
date: {
$nin: [{
date: {
$lt: "Mon Jan 01 2024 05:00:00 GMT+0500 (Pakistan Standard Time)",
},
}],
},
},
],
}
以上查询对我有用。我希望它有帮助:)