java - Aggregation Project Group By extracted day, month and year with Spring Data -


to direct, how do this:

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

with spring data

i tried , other forms , not successfull

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")         ); 

i need group day, month , year in mongodb, or else need convert grouped data in code.

thanks in advance

you running limitation of spring mongo in can field calculations in single $project stage, , indeed writing separate $project since discover cannot project custom named fields directly in $group _id @ present either.

so better off keeping in $group, using different method rounding adjusted dates local time.

the better way write $group therefore be:

{ "$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" } }} 

of course use sort of structure spring-mongo need custom implementation of aggregation stage operation can take defined 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);     } } 

which use in context this:

    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")     ); 

since custom class abstracts same basic class used built in helper methods, can used alongside them shown.

how basic process date math works here when $subtract 1 bson date object result milliseconds of difference, , in case epoch date ( date(0) ) extracts milliseconds value. allows math round current date value modulo ( $mod ) number of milliseconds in 1 day.

much tried, when $add millisecond value bson date object returned value again bson date. adding object representing epoch returns new date object, rounded current date.

this lot more useful extracting parts via date aggregation operators, , works out bit shorter code, when adjusting time utc doing here.

though contruction of $group here bit more terse helper functions of spring mongo trying avoid, lot more efficient in end running separate $project stage transform field values want in $group stage anyway.


Comments