use of co.cask.cdap.data2.dataset2.lib.timeseries.FactScanResult in project cdap by caskdata.
the class DefaultCube method getTimeSeries.
private Table<Map<String, String>, String, Map<Long, Long>> getTimeSeries(CubeQuery query, FactScanner scanner) {
// {dimension values, measure} -> {time -> value}s
Table<Map<String, String>, String, Map<Long, Long>> result = HashBasedTable.create();
int count = 0;
while (scanner.hasNext()) {
FactScanResult next = scanner.next();
incrementMetric("cube.query.scan.records.count", 1);
boolean skip = false;
// using tree map, as we are using it as a key for a map
Map<String, String> seriesDimensions = Maps.newTreeMap();
for (String dimensionName : query.getGroupByDimensions()) {
// todo: use Map<String, String> instead of List<DimensionValue> into a String, String, everywhere
for (DimensionValue dimensionValue : next.getDimensionValues()) {
if (dimensionName.equals(dimensionValue.getName())) {
if (dimensionValue.getValue() == null) {
// Currently, we do NOT return null as grouped by value.
// Depending on whether dimension is required or not the records with null value in it may or may not be
// in aggregation. At this moment, the choosing of the aggregation for query doesn't look at this, so
// potentially null may or may not be included in results, depending on the aggregation selected
// querying. We don't want to produce inconsistent results varying due to different aggregations selected,
// so don't return nulls in any of those cases.
skip = true;
continue;
}
seriesDimensions.put(dimensionName, dimensionValue.getValue());
break;
}
}
}
if (skip) {
incrementMetric("cube.query.scan.skipped.count", 1);
continue;
}
for (TimeValue timeValue : next) {
Map<Long, Long> timeValues = result.get(seriesDimensions, next.getMeasureName());
if (timeValues == null) {
result.put(seriesDimensions, next.getMeasureName(), Maps.<Long, Long>newHashMap());
}
AggregationFunction function = query.getMeasurements().get(next.getMeasureName());
if (AggregationFunction.SUM == function) {
Long value = result.get(seriesDimensions, next.getMeasureName()).get(timeValue.getTimestamp());
value = value == null ? 0 : value;
value += timeValue.getValue();
result.get(seriesDimensions, next.getMeasureName()).put(timeValue.getTimestamp(), value);
} else if (AggregationFunction.MAX == function) {
Long value = result.get(seriesDimensions, next.getMeasureName()).get(timeValue.getTimestamp());
value = value != null && value > timeValue.getValue() ? value : timeValue.getValue();
result.get(seriesDimensions, next.getMeasureName()).put(timeValue.getTimestamp(), value);
} else if (AggregationFunction.MIN == function) {
Long value = result.get(seriesDimensions, next.getMeasureName()).get(timeValue.getTimestamp());
value = value != null && value < timeValue.getValue() ? value : timeValue.getValue();
result.get(seriesDimensions, next.getMeasureName()).put(timeValue.getTimestamp(), value);
} else if (AggregationFunction.LATEST == function) {
result.get(seriesDimensions, next.getMeasureName()).put(timeValue.getTimestamp(), timeValue.getValue());
} else {
// should never happen: developer error
throw new RuntimeException("Unknown MeasureType: " + function);
}
}
if (++count >= MAX_RECORDS_TO_SCAN) {
break;
}
}
return result;
}
Aggregations