use of org.hisp.dhis.common.DimensionalItemObject in project dhis2-core by dhis2.
the class DefaultQueryPlanner method groupByPeriodType.
/**
* If periods appear as dimensions in the given query; groups the query into
* sub queries based on the period type of the periods. Sets the period type
* name on each query. If periods appear as filters; replaces the period filter
* with one filter for each period type. Sets the dimension names and filter
* names respectively.
*/
@Override
public List<DataQueryParams> groupByPeriodType(DataQueryParams params) {
List<DataQueryParams> queries = new ArrayList<>();
if (params.isSkipPartitioning()) {
queries.add(params);
} else if (!params.getPeriods().isEmpty()) {
ListMap<String, DimensionalItemObject> periodTypePeriodMap = PartitionUtils.getPeriodTypePeriodMap(params.getPeriods());
for (String periodType : periodTypePeriodMap.keySet()) {
DataQueryParams query = DataQueryParams.newBuilder(params).addOrSetDimensionOptions(PERIOD_DIM_ID, DimensionType.PERIOD, periodType.toLowerCase(), periodTypePeriodMap.get(periodType)).withPeriodType(periodType).build();
queries.add(query);
}
} else if (!params.getFilterPeriods().isEmpty()) {
DimensionalObject filter = params.getFilter(PERIOD_DIM_ID);
ListMap<String, DimensionalItemObject> periodTypePeriodMap = PartitionUtils.getPeriodTypePeriodMap(filter.getItems());
DataQueryParams.Builder query = DataQueryParams.newBuilder(params).removeFilter(PERIOD_DIM_ID).withPeriodType(// Using first period type
periodTypePeriodMap.keySet().iterator().next());
for (String periodType : periodTypePeriodMap.keySet()) {
query.addFilter(new BaseDimensionalObject(filter.getDimension(), filter.getDimensionType(), periodType.toLowerCase(), filter.getDisplayName(), periodTypePeriodMap.get(periodType)));
}
queries.add(query.build());
} else {
queries.add(DataQueryParams.newBuilder(params).build());
return queries;
}
if (queries.size() > 1) {
log.debug(String.format("Split on period type: %d", queries.size()));
}
return queries;
}
use of org.hisp.dhis.common.DimensionalItemObject in project dhis2-core by dhis2.
the class DefaultQueryPlanner method groupByDaysInPeriod.
/**
* Groups the given query into sub queries based on the number of days in the
* aggregation period. This only applies if the aggregation type is
* {@link AggregationType#AVERAGE_SUM_INT} and the query has at least one period as
* dimension option. This is necessary since the number of days in the aggregation
* period is part of the expression for aggregating the value.
*
* @param params the data query parameters.
* @return a list of {@link DataQueryParams}.
*/
private List<DataQueryParams> groupByDaysInPeriod(DataQueryParams params) {
List<DataQueryParams> queries = new ArrayList<>();
if (params.getPeriods().isEmpty() || !params.isAggregationType(AggregationType.AVERAGE_SUM_INT)) {
queries.add(DataQueryParams.newBuilder(params).build());
return queries;
}
ListMap<Integer, DimensionalItemObject> daysPeriodMap = QueryPlannerUtils.getDaysPeriodMap(params.getPeriods());
DimensionalObject periodDim = params.getDimension(PERIOD_DIM_ID);
for (Integer days : daysPeriodMap.keySet()) {
DataQueryParams query = DataQueryParams.newBuilder(params).addOrSetDimensionOptions(periodDim.getDimension(), periodDim.getDimensionType(), periodDim.getDimensionName(), daysPeriodMap.get(days)).build();
queries.add(query);
}
if (queries.size() > 1) {
log.debug(String.format("Split on days in period: %d", queries.size()));
}
return queries;
}
use of org.hisp.dhis.common.DimensionalItemObject in project dhis2-core by dhis2.
the class DefaultQueryPlanner method splitByDimension.
// -------------------------------------------------------------------------
// Supportive methods
// -------------------------------------------------------------------------
/**
* Splits the given list of queries in sub queries on the given dimension.
*/
private DataQueryGroups splitByDimension(DataQueryGroups queryGroups, String dimension, int optimalQueries) {
int optimalForSubQuery = MathUtils.divideToFloor(optimalQueries, queryGroups.getLargestGroupSize());
List<DataQueryParams> subQueries = new ArrayList<>();
for (DataQueryParams query : queryGroups.getAllQueries()) {
DimensionalObject dim = query.getDimension(dimension);
List<DimensionalItemObject> values = null;
if (dim == null || (values = dim.getItems()) == null || values.isEmpty()) {
subQueries.add(DataQueryParams.newBuilder(query).build());
continue;
}
List<List<DimensionalItemObject>> valuePages = new PaginatedList<>(values).setNumberOfPages(optimalForSubQuery).getPages();
for (List<DimensionalItemObject> valuePage : valuePages) {
DataQueryParams subQuery = DataQueryParams.newBuilder(query).withDimensionOptions(dim.getDimension(), valuePage).build();
subQueries.add(subQuery);
}
}
if (subQueries.size() > queryGroups.getAllQueries().size()) {
log.debug(String.format("Split on dimension %s: %d", dimension, (subQueries.size() / queryGroups.getAllQueries().size())));
}
return DataQueryGroups.newBuilder().withQueries(subQueries).build();
}
use of org.hisp.dhis.common.DimensionalItemObject in project dhis2-core by dhis2.
the class DefaultQueryPlanner method groupByAggregationType.
/**
* Groups the given query in sub queries based on the aggregation type of its
* data elements. The aggregation type can be sum, average aggregation or
* average disaggregation. Sum means that the data elements have sum aggregation
* operator. Average aggregation means that the data elements have the average
* aggregation operator and that the period type of the data elements have
* higher or equal frequency than the aggregation period type. Average disaggregation
* means that the data elements have the average aggregation operator and
* that the period type of the data elements have lower frequency than the
* aggregation period type. Average bool means that the data elements have the
* average aggregation operator and the bool value type.
* <p>
* If no data elements are present, the aggregation type will be determined
* based on the first data element in the first data element group in the
* first data element group set in the query.
* <p>
* If the aggregation type is already set/overridden in the request, the
* query will be returned unchanged. If there are no data elements or data
* element group sets specified the aggregation type will fall back to sum.
*
* @param params the data query parameters.
* @return a list of {@link DataQueryParams}.
*/
private List<DataQueryParams> groupByAggregationType(DataQueryParams params) {
List<DataQueryParams> queries = new ArrayList<>();
if (!params.getDataElements().isEmpty()) {
ListMap<AggregationType, DimensionalItemObject> aggregationTypeDataElementMap = QueryPlannerUtils.getAggregationTypeDataElementMap(params);
for (AggregationType aggregationType : aggregationTypeDataElementMap.keySet()) {
DataQueryParams query = DataQueryParams.newBuilder(params).withDataElements(aggregationTypeDataElementMap.get(aggregationType)).withAggregationType(aggregationType).build();
queries.add(query);
}
} else if (!params.getDataElementGroupSets().isEmpty()) {
DimensionalObject degs = params.getDataElementGroupSets().get(0);
DataElementGroup deg = (DataElementGroup) (degs.hasItems() ? degs.getItems().get(0) : null);
AggregationType aggregationType = ObjectUtils.firstNonNull(params.getAggregationType(), SUM);
if (deg != null && !deg.getMembers().isEmpty()) {
PeriodType periodType = PeriodType.getPeriodTypeByName(params.getPeriodType());
aggregationType = ObjectUtils.firstNonNull(params.getAggregationType(), deg.getAggregationType());
aggregationType = QueryPlannerUtils.getAggregationType(deg.getValueType(), aggregationType, periodType, deg.getPeriodType());
}
DataQueryParams query = DataQueryParams.newBuilder(params).withAggregationType(aggregationType).build();
queries.add(query);
} else {
DataQueryParams query = DataQueryParams.newBuilder(params).withAggregationType(ObjectUtils.firstNonNull(params.getAggregationType(), SUM)).build();
queries.add(query);
}
if (queries.size() > 1) {
log.debug(String.format("Split on aggregation type: %d", queries.size()));
}
return queries;
}
use of org.hisp.dhis.common.DimensionalItemObject in project dhis2-core by dhis2.
the class DefaultPredictorService method predict.
// -------------------------------------------------------------------------
// Predictor run
// -------------------------------------------------------------------------
@Override
public int predict(Predictor predictor, Date startDate, Date endDate) {
log.info("Predicting for " + predictor.getName() + " from " + startDate.toString() + " to " + endDate.toString());
Expression generator = predictor.getGenerator();
Expression skipTest = predictor.getSampleSkipTest();
DataElement outputDataElement = predictor.getOutput();
Set<String> aggregates = expressionService.getAggregatesInExpression(generator.getExpression());
Map<String, Double> constantMap = constantService.getConstantMap();
List<Period> outputPeriods = getPeriodsBetweenDates(predictor.getPeriodType(), startDate, endDate);
ListMap<Period, Period> samplePeriodsMap = getSamplePeriodsMap(outputPeriods, predictor);
Set<Period> allSamplePeriods = samplePeriodsMap.uniqueValues();
Set<DataElementOperand> dataElementOperands = getDataElementOperands(aggregates, skipTest);
User currentUser = currentUserService.getCurrentUser();
DataElementCategoryOptionCombo outputOptionCombo = predictor.getOutputCombo() == null ? categoryService.getDefaultDataElementCategoryOptionCombo() : predictor.getOutputCombo();
List<OrganisationUnit> orgUnits = organisationUnitService.getOrganisationUnitsAtOrgUnitLevels(predictor.getOrganisationUnitLevels(), currentUser.getOrganisationUnits());
int predictionCount = 0;
for (OrganisationUnit orgUnit : orgUnits) {
MapMapMap<Period, String, DimensionalItemObject, Double> dataMap = dataElementOperands.isEmpty() ? null : dataValueService.getDataElementOperandValues(dataElementOperands, allSamplePeriods, orgUnit);
applySkipTest(dataMap, skipTest, constantMap);
for (Period period : outputPeriods) {
ListMapMap<String, String, Double> aggregateSampleMap = getAggregateSamples(dataMap, aggregates, samplePeriodsMap.get(period), constantMap);
for (String aoc : aggregateSampleMap.keySet()) {
ListMap<String, Double> aggregateValueMap = aggregateSampleMap.get(aoc);
Double value = expressionService.getExpressionValue(generator, new HashMap<>(), constantMap, null, period.getDaysInPeriod(), aggregateValueMap);
if (value != null && !value.isNaN() && !value.isInfinite()) {
writeDataValue(outputDataElement, period, orgUnit, outputOptionCombo, categoryService.getDataElementCategoryOptionCombo(aoc), value.toString(), currentUser.getUsername());
predictionCount++;
}
}
}
}
log.info("Generated " + predictionCount + " predictions for " + predictor.getName() + " from " + startDate.toString() + " to " + endDate.toString());
return predictionCount;
}
Aggregations