Pillola 11: Usare DateOperators in Spring Data MongoDB

Pubblicato il 14/11/2022

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;
	}

}
  • I contenuti di questo articolo sono rilasciati con licenza CC-BY 4.0
  • Eventuali spezzoni di codice presentati seguono, dove non dichiarato, licenza MIT