Pillola 11: Usare DateOperators in Spring Data MongoDB
Problema
Conteggiare per giorno del mese le presenze di sensori localizzati a Sydney.
Come scrivo il codice Spring Data MongoDB che rappresenta questa aggregazione ?
Contesto
MonboDB salva le date in UTC.
Sydney è in timezone UTC+10/UTC+11.
Per estrarre giorno e mese corretto devo specificare la timezone relativa come parametro della funzione $month
e $dayOfMonth
.
L’aggregazione MongoDB risulterà la seguente:
db.getCollection('presence').aggregate([
{$group: {
_id: {
dayOfMonth: {
$dayOfMonth :{
date: '$date',
timezone: 'Australia/Sydney'
}
},
month: {
$month :{
date: '$date',
timezone: 'Australia/Sydney'
}
}
},
howMany: {$sum: 1}}}
])
Soluzione
Usare la classe DateOperators
che espone una serie di classi statiche per utilizzare le funzioni sulle date in MongoDB potendo, se necessario, specificare la Timezone
.
List<AggregationOperation> operations = new ArrayList<AggregationOperation>();
Timezone sydneyTimezone = DateOperators.Timezone.fromZone(ZoneId.of("Australia/Sydney"));
operations.add(
Aggregation.project("sensorId")
.and(DateOperators.DayOfMonth.dayOfMonth("date").withTimezone(sydneyTimezone)).as("dayOfMonth")
.and(DateOperators.Month.monthOf("date").withTimezone(sydneyTimezone)).as("month")
);
operations.add(Aggregation.group("dayOfMonth","month").count().as("howMany"));
Aggregation aggregation = Aggregation.newAggregation(operations);
AggregationResults<Metrics> result = mongo.aggregate(aggregation, PresenceDocument.class, Metrics.class);
@Document(collection = "presence")
public class PresenceDocument {
@Id
private String id;
private String sensorId;
private ZonedDateTime date;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSensorId() {
return sensorId;
}
public void setSensorId(String sensorId) {
this.sensorId = sensorId;
}
public ZonedDateTime getDate() {
return date;
}
public void setDate(ZonedDateTime date) {
this.date = date;
}
}
public class Metrics {
private GroupId id;
private int howMany;
public static class GroupId {
private int dayOfMonth;
private int month;
public int getDayOfMonth() {
return dayOfMonth;
}
public void setDayOfMonth(int dayOfMonth) {
this.dayOfMonth = dayOfMonth;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
}
public GroupId getId() {
return id;
}
public void setId(GroupId id) {
this.id = id;
}
public int getHowMany() {
return howMany;
}
public void setHowMany(int howMany) {
this.howMany = howMany;
}
}