基于离散日期范围的分组

Group based on discrete date ranges

我是 MongoDB 的新手,我一直在努力使特定查询正常工作,但运气不佳。 我有一个包含数百万个具有日期和数量的文档的集合,我想获取特定时间段的聚合。 例如,我想获取 1/1/2015 - 15/1/20151/2/2015 - 15/2/2015

之间期间的计数、金额总和

样本集是

{  "_id" : "148404972864202083547392254",  "account" : "3600",   "amount" : 50, "date" : ISODate("2017-01-01T12:02:08.642Z")}

{  "_id" : "148404972864202085437392254",  "account" : "3600",   "amount" : 50, "date" : ISODate("2017-01-03T12:02:08.642Z")}

{  "_id" : "148404372864202083547392254",  "account" : "3600",   "amount" : 70, "date" : ISODate("2017-01-09T12:02:08.642Z")}

{  "_id" : "148404972864202083547342254",  "account" : "3600",   "amount" : 150, "date" : ISODate("2017-01-22T12:02:08.642Z")}

{  "_id" : "148404922864202083547392254",  "account" : "3600",   "amount" : 200, "date" : ISODate("2017-02-02T12:02:08.642Z")}

{  "_id" : "148404972155502083547392254",  "account" : "3600",   "amount" : 30, "date" : ISODate("2017-02-7T12:02:08.642Z")}

{  "_id" : "148404972864202122254732254",  "account" : "3600",   "amount" : 10, "date" : ISODate("2017-02-10T12:02:08.642Z")}

对于 1/1/2017 - 10/10/20171/2/2017 - 10/2/2017 之间的日期范围,输出将如下所示:

是否可以使用如此不同的日期范围?代码将在 Java 中,但作为 mongo 中的示例,有人可以帮助我吗?

一定有比这更优雅的解决方案。无论如何,您可以将其包装到一个函数中并概括与日期相关的参数。

首先,您需要在确定项目进入哪个范围的同时进行投影(注意巨大的 $switch 表达式)。默认情况下,项目进入 'null' 范围。

然后,您过滤掉不符合您的条件(即范围 != null)的结果。

最后一步是按范围对项目进行分组并进行所有需要的计算。

db.items.aggregate([
  { $project : {
    amount : true,
    account : true,
    date : true,
    range : {
      $switch : {
        branches : [
          {
            case : {
              $and : [
                { $gte : [ "$date", ISODate("2017-01-01T00:00:00.000Z") ] },
                { $lt : [ "$date", ISODate("2017-01-10T00:00:00.000Z") ] }
              ]
            },
            then : { $concat : [
              { $dateToString: { format: "%d/%m/%Y", date: ISODate("2017-01-01T00:00:00.000Z") } },
              { $literal : " - " },
              { $dateToString: { format: "%d/%m/%Y", date: ISODate("2017-01-10T00:00:00.000Z") } }
            ] }
          },
          {
            case : {
              $and : [
                { $gte : [ "$date", ISODate("2017-02-01T00:00:00.000Z") ] },
                { $lt : [ "$date", ISODate("2017-02-10T00:00:00.000Z") ] }
              ]
            },
            then : { $concat : [
              { $dateToString: { format: "%d/%m/%Y", date: ISODate("2017-02-01T00:00:00.000Z") } },
              { $literal : " - " },
              { $dateToString: { format: "%d/%m/%Y", date: ISODate("2017-02-10T00:00:00.000Z") } }
            ] }
          }
        ],
        default : null
      }
    }
  } },
  { $match : { range : { $ne : null } } },
  { $group : {
    _id : "$range",
    count : { $sum : 1 },
    "amount summation" : { $sum : "$amount" }
  } }
])

根据您的数据,它将给出以下结果*:

{ "_id" : "01/02/2017 - 10/02/2017", "count" : 2, "amount summation" : 230 }
{ "_id" : "01/01/2017 - 10/01/2017", "count" : 3, "amount summation" : 170 }

*我相信您的问题中几乎没有错别字,这就是数据看起来不同的原因。