按时间间隔分组spring-data-mongo

时间:2019-02-07 21:58:32

标签: mongodb spring-data-mongodb

下面是我的文档结构:

{
   "_id":"5c59c35d8610f702d00e6f70",
   "stationId":"2",
   "listenerId":"807",
   "streamId":"37",
   "userAgentId":"7",
   "botDefinitionId":"18",
   "ipAddress":"50.116.14.48",
   "startTime":"2018-02-06T12:51:59.000Z",
   "endTime":"2018-02-06T12:53:56.000Z",
   "listenLength":"117",
   "totalDataUsed":"1433582",
}

使用spring数据mongo,我想将它们分组为时间窗口(假设间隔15分钟)。我创建了以下工作查询:

{
   '_id':{
      'year':{
         '$year':'$startTime'
      },
      'week':{
         '$week':'$startTime'
      },
      'dayOfMonth':{
         '$dayOfMonth':'$startTime'
      },
      'month':{
         '$month':'$startTime'
      },
      'hour':{
         '$hour':'$startTime'
      },
      'interval':{
         '$subtract':[
            {
               '$minute':'$startTime'
            },
            {
               '$mod':[
                  {
                     '$minute':'$startTime'
                  },
                  15
               ]
            }
         ]
      }
   },
   'count':{
      '$sum':1
   }
}

然后将以下文件退给我:

_id:{
   year:2018   week:15   dayOfMonth:18   month:4   hour:18   interval:45
},
count:9

如何使用GroupOperation在spring-data-mongo中指定这种聚合形式?

1 个答案:

答案 0 :(得分:1)

我想到的一种方法是在$ project阶段调用函数,而不是在$ group阶段调用函数。

使用DateOperator类提取诸如小时,分钟,年份等字段。 然后将SpEL andExpression用于您的间隔字段,如下:

andExpression("minute - minute % 15").as("interval")

这将使用小时,间隔,年份等字段来重塑文档,然后将它们分组到间隔和所需的其他字段上。

Aggregation agg = Aggregation.newAggregation(

    Aggregation.project()
        .and(DateOperators.Minute.minute("$timestamp")).as("minute")
        .and(DateOperators.Hour.hour("$timestamp")).as("hour")
        .and(DateOperators.DayOfMonth.dayOfMonth("$timestamp")).as("dayOfMonth"),

    Aggregation.project("hour","dayOfMonth","minute")
        .andExpression("minute - minute % 15").as("interval"),

    Aggregation.group("hour","dayOfMonth","interval")
        .addToSet("hour").as("hour")
        .addToSet("dayOfMonth").as("dayOfMonth")
        .addToSet("interval").as("interval")
        .count().as("count")
);

List<QueryResult> result = mongoTemplate.aggregate(agg, "collection_name", QueryResult.class).getMappedResults();