MongoDB 中按年和月的聚合查询

问题描述 投票:0回答:2

我正在使用 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
2个回答
0
投票

我建议升级到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))

0
投票

$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)",
          },
        }],
      },
    },
  ],
}

以上查询对我有用。我希望它有帮助:)

© www.soinside.com 2019 - 2024. All rights reserved.