聚合项目组通过Spring Data提取日,月和年

要直接,我该怎么做:

group._id = { year: { $year : [{ $subtract: [ "$timestamp", 25200000 ]}] }, month: { $month : [{ $subtract: [ "$timestamp", 25200000 ]}] }, day: { $dayOfMonth : [{ $subtract: [ "$timestamp", 25200000 ]}] } }; 

用spring数据

我已经尝试了这个和其他一些forms并没有成功

 Aggregation aggregation = Aggregation.newAggregation( Aggregation.match(c), Aggregation.project("programa", "custo", "duracao", "dataHora") .andExpression("dataHora").minus(25200000).extractDayOfMonth().as("dia") .andExpression("dataHora").minus(25200000).extractMonth().as("mes") .andExpression("dataHora").minus(25200000).extractYear().as("ano"), Aggregation.group("programa", "ano", "mes", "dia") .count().as("count") .sum("custo").as("valorTotal") .sum("duracao").as("duracaoTotal") .first("dataHora").as("dataHora"), Aggregation.sort(Direction.ASC, "dataHora") ); 

我需要在mongodb中按天,月和年进行分组,否则我需要在代码中转换所有这些分组数据。

提前致谢

你在单个$project阶段的字段计算中遇到了spring mongo的限制,事实上你可能已经写了一个单独的$project因为你发现你不能直接在$group投影自定义命名字段目前也是$group

因此,最好将这一切保留在$group ,以及使用不同的方法将调整后的日期四舍五入到当地时间。

因此,编写$group的更好方法是:

 { "$group": { "_id": { "programa": "$programa", "dataHora": { "$add": [ { "$subtract": [ { "$subtract": [{ "$subtract": ["$dataHora", new Date(0)] }, 25200000 ] }, { "$mod": [ { "$subtract": [{ "$subtract": ["$dataHora", new Date(0)] }, 25200000 ] }, 1000 * 60 * 60 * 24 ]} ]}, new Date(0) ] } }, "count": { "$sum": 1 }, "valorTotal": { "$sum": "$custo" }, "duracaoTotal": { "$sum": "$duracao" }, "dataHora": { "$first": "$dataHora" } }} 

当然要使用spring-mongo这种结构,你需要一个聚合阶段操作的自定义实现,它可以采用一个定义的DBObject

 public class CustomGroupOperation implements AggregationOperation { private DBObject operation; public CustomGroupOperation (DBObject operation) { this.operation = operation; } @Override public DBObject toDBObject(AggregationOperationContext context) { return context.getMappedObject(operation); } } 

然后你在上下文中使用这样的:

  Aggregation aggregation = Aggregation.newAggregation( Aggregation.match(c), new CustomGroupOperation( new BasicDBObject("$group", new BasicDBObject("_id", new BasicDBObject("programa","$programa") .append("dataHora", new BasicDBObject("$add",Arrays.asList( new BasicDBObject("$subtract",Arrays.asList( new BasicDBObject("$subtract",Arrays.asList( new BasicDBObject("$subtract",Arrays.asList( "$dataHora", new Date(0) )), 25200000 )), new BasicDBObject("$mod",Arrays.asList( new BasicDBObject("$subtract",Arrays.asList( new BasicDBObject("$subtract",Arrays.asList( "$dataHora", new Date(0) )), 25200000 )), 1000 * 60 * 60 * 24 )) )), new Date(0) )) ) ) .append("count",new BasicDBObject("$sum",1)) .append("valorTotal",new BasicDBObject("$sum","$custo")) .append("duracaoTotal",new BasicDBObject("$sum","$duracao")) .append("dataHora",new BasicDBObject("$first","$dataHora")) ) ), Aggregation.sort(Direction.ASC,"_id.dataHora") ); 

由于自定义类是从内置辅助方法使用的相同基本类中抽象出来的,因此它可以与它们一起使用,如图所示。

这里使用日期数学的基本过程是如何在$subtract另一个BSON Date对象中$subtract ,然后结果是毫秒的差异,在这种情况下是从纪元日期(Date(0))中提取毫秒数值。 这允许您通过模数( $mod )从一天中的毫秒数开始舍入到当前日期值。

就像你最初尝试的那样,当你将$add毫秒值$add到BSON Date对象时,返回的值又是BSON Date。 因此,添加到表示纪元的对象会返回一个新的日期对象,但会四舍五入到当前日期。

这通常比通过日期聚合运算符提取部件更有用,而且编码时间也要短一些,特别是在调整UTC时间时,就像在这里一样。

虽然这里$group的构造比spring mongo的helper函数试图避免的要简单一些,但最终它比运行一个单独的$project阶段来转换字段值更有效率。无论如何都想在$group阶段。