基于离散日期范围的组

时间:2017-03-19 06:17:58

标签: mongodb mongodb-query aggregation-framework mongodb-java

我是MongoDB的新手,我一直在努力让一个特定的查询无需运气。 我有一个包含数百万个具有日期和金额的文档的集合,我想获得特定时间段的聚合。 例如,我想获取1/1/2015 - 15/1/2015之间和1/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之间的日期范围,输出将如下所示:

  • 1/1/2017 - 10/1/2017 - count = 3,金额总和:170
  • 10/2/2017 - 15/2/2017 - count = 2,金额总和:40

是否可以使用这些不同的日期范围?代码将使用Java,但作为mongo的一个例子,有人可以帮助我吗?

1 个答案:

答案 0 :(得分:1)

必须有比这更优雅的解决方案。无论如何,你可以将它包装成一个函数并概括与日期相关的参数。

首先,您需要在决定项目的范围的同时进行投影(请注意巨大的$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 }

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