首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MongoDB中按年份和月份分列的聚合查询

MongoDB中按年份和月份分列的聚合查询
EN

Stack Overflow用户
提问于 2021-12-09 12:11:35
回答 1查看 1.2K关注 0票数 1

我使用的是MongoDB 4.2。

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

代码语言:javascript
复制
[
  {
    "_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")
  }
]

聚合查询如下。

代码语言:javascript
复制
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
      },
      
    }
  }
])

上面的查询返回以下输出。

代码语言:javascript
复制
[
  {
    "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的数据,因此在match组中提到的日期范围内添加缺少月份的0计数。
  2. 在MMM中添加一个名为TITLE的新字段(类似于2021年7月)
  3. 基于上面的_id对输出进行排序

总体上,预期产出如下。

代码语言:javascript
复制
[
  {
    "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游乐场供你参考。

非常感谢你的帮助。

EN

回答 1

Stack Overflow用户

发布于 2021-12-09 16:37:28

我建议升级到MOGO5.0,它提供了一些很好的函数,$dateTrunc$dateAdd$dateDiff,在本例中非常有用。如果没有可用的,则需要处理毫秒、$dateFromParts$dateToParts。不过,它还需要一些代码。

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

或者您可以使用$switch构建一个月名查找。

代码语言:javascript
复制
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))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70289720

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档