package de.asideas.crowdsource.repository; import de.asideas.crowdsource.domain.model.ProjectEntity; import de.asideas.crowdsource.presentation.statistics.requests.TimeRangedStatisticsRequest; import de.asideas.crowdsource.presentation.statistics.results.BarChartStatisticsResult; import de.asideas.crowdsource.presentation.statistics.results.LineChartStatisticsResult; import de.asideas.crowdsource.service.statistics.StatisticsActionUtil; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapreduce.MapReduceResults; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import static de.asideas.crowdsource.domain.model.CommentEntity.COLLECTION_NAME; public class CommentRepositoryImpl implements CommentRepositoryCustom { static final String CHART_NAME_SUM_COMMENTS = "Summe Kommentare"; private final MongoTemplate mongoTemplate; @Autowired public CommentRepositoryImpl(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } @Override public List<BarChartStatisticsResult> countCommentsGroupByProject(int projectCount) { final String map = "function(){ emit(this.project.$id , 1 ); } "; final String reduce = "function(key,values){ return values.length;}"; MapReduceResults<KeyValuePair> results = mongoTemplate.mapReduce(COLLECTION_NAME, map, reduce, KeyValuePair.class); final List<KeyValuePair> sortedList = new ArrayList<>(); for (KeyValuePair result : results) { sortedList.add(result); } Collections.sort(sortedList); List<BarChartStatisticsResult> res = new ArrayList<>(projectCount); for (KeyValuePair kv : sortedList) { ProjectEntity project = mongoTemplate.findOne(new Query(Criteria.where("id").is(kv.getId())), ProjectEntity.class); if (project != null) { res.add(new BarChartStatisticsResult(kv.getId(), project.getTitle(), kv.getValue())); } if (res.size() >= projectCount) { break; } } return res; } @Override public LineChartStatisticsResult sumCommentsGroupByCreatedDate(TimeRangedStatisticsRequest request) { // Emit UTC millis (only year, month, week and day are taken into account) of createdDate as key // Value is set to 1 to sum up later (reduce) String map = "function () { " + " var day = Date.UTC(this.createdDate.getFullYear(), this.createdDate.getMonth(), this.createdDate.getDate()); " + " emit(day.toString(), 1); " + "}"; // Reduce all the values for one "key" (for details about key, see above) by summing up each value. final String reduce = "function(key,values){ return values.length;}"; Query filter = Query.query(Criteria.where("createdDate").gte(request.getStartDate()).lte(request.getEndDate())); MapReduceResults<KeyValuePair> sumResults = mongoTemplate.mapReduce( filter, COLLECTION_NAME, map, reduce, KeyValuePair.class ); return toLineChartStatisticsResult(sumResults, request); } private LineChartStatisticsResult toLineChartStatisticsResult(MapReduceResults<KeyValuePair> sumResults, TimeRangedStatisticsRequest request) { Map<String, Long> results = new LinkedHashMap<>(); for (KeyValuePair vo : sumResults) { DateTime dateFromDbId; try { dateFromDbId = new DateTime(Long.parseLong(vo.getId()), DateTimeZone.UTC); } catch (NumberFormatException nfe) { throw new IllegalStateException("MapReduce emitted wrong format for id / key field. Expected UTC millis.", nfe); } results.put(StatisticsActionUtil.formatDate(dateFromDbId), vo.getValue()); } return new LineChartStatisticsResult( CHART_NAME_SUM_COMMENTS, StatisticsActionUtil.fillMap(StatisticsActionUtil.getDefaultMap(request), results) ); } public static class KeyValuePair implements Comparable<KeyValuePair> { String id; Long value; public KeyValuePair(String id, Long value) { this.id = id; this.value = value; } public String getId() { return id; } public void setId(String id) { this.id = id; } public Long getValue() { return value; } public void setValue(Long value) { this.value = value; } @Override public int compareTo(KeyValuePair o) { if (this.value < o.value) { return 1; } else if (this.value > o.value) { return -1; } else { return 0; } } } }