Search in sources :

Example 1 with ExpressionPostAggregator

use of io.druid.query.aggregation.post.ExpressionPostAggregator in project druid by druid-io.

the class DefaultLimitSpecTest method testBuildWithExplicitOrder.

@Test
public void testBuildWithExplicitOrder() {
    DefaultLimitSpec limitSpec = new DefaultLimitSpec(ImmutableList.of(new OrderByColumnSpec("k1", OrderByColumnSpec.Direction.ASCENDING)), 2);
    Function<Sequence<Row>, Sequence<Row>> limitFn = limitSpec.build(ImmutableList.<DimensionSpec>of(new DefaultDimensionSpec("k1", "k1")), ImmutableList.<AggregatorFactory>of(new LongSumAggregatorFactory("k2", "k2")), ImmutableList.<PostAggregator>of(new ConstantPostAggregator("k3", 1L)));
    Assert.assertEquals(ImmutableList.of(testRowsList.get(0), testRowsList.get(1)), Sequences.toList(limitFn.apply(testRowsSequence), new ArrayList<Row>()));
    // if there is an aggregator with same name then that is used to build ordering
    limitFn = limitSpec.build(ImmutableList.<DimensionSpec>of(new DefaultDimensionSpec("k1", "k1")), ImmutableList.<AggregatorFactory>of(new LongSumAggregatorFactory("k1", "k1")), ImmutableList.<PostAggregator>of(new ConstantPostAggregator("k3", 1L)));
    Assert.assertEquals(ImmutableList.of(testRowsList.get(2), testRowsList.get(0)), Sequences.toList(limitFn.apply(testRowsSequence), new ArrayList<Row>()));
    // if there is a post-aggregator with same name then that is used to build ordering
    limitFn = limitSpec.build(ImmutableList.<DimensionSpec>of(new DefaultDimensionSpec("k1", "k1")), ImmutableList.<AggregatorFactory>of(new LongSumAggregatorFactory("k2", "k2")), ImmutableList.<PostAggregator>of(new ArithmeticPostAggregator("k1", "+", ImmutableList.<PostAggregator>of(new ConstantPostAggregator("x", 1), new ConstantPostAggregator("y", 1)))));
    Assert.assertEquals((List) ImmutableList.of(testRowsList.get(2), testRowsList.get(0)), (List) Sequences.toList(limitFn.apply(testRowsSequence), new ArrayList<Row>()));
    // makes same result
    limitFn = limitSpec.build(ImmutableList.<DimensionSpec>of(new DefaultDimensionSpec("k1", "k1")), ImmutableList.<AggregatorFactory>of(new LongSumAggregatorFactory("k2", "k2")), ImmutableList.<PostAggregator>of(new ExpressionPostAggregator("k1", "1 + 1")));
    Assert.assertEquals((List) ImmutableList.of(testRowsList.get(2), testRowsList.get(0)), (List) Sequences.toList(limitFn.apply(testRowsSequence), new ArrayList<Row>()));
}
Also used : DimensionSpec(io.druid.query.dimension.DimensionSpec) DefaultDimensionSpec(io.druid.query.dimension.DefaultDimensionSpec) ArithmeticPostAggregator(io.druid.query.aggregation.post.ArithmeticPostAggregator) PostAggregator(io.druid.query.aggregation.PostAggregator) ExpressionPostAggregator(io.druid.query.aggregation.post.ExpressionPostAggregator) ArithmeticPostAggregator(io.druid.query.aggregation.post.ArithmeticPostAggregator) ConstantPostAggregator(io.druid.query.aggregation.post.ConstantPostAggregator) LongSumAggregatorFactory(io.druid.query.aggregation.LongSumAggregatorFactory) ConstantPostAggregator(io.druid.query.aggregation.post.ConstantPostAggregator) ArrayList(java.util.ArrayList) Sequence(io.druid.java.util.common.guava.Sequence) AggregatorFactory(io.druid.query.aggregation.AggregatorFactory) LongSumAggregatorFactory(io.druid.query.aggregation.LongSumAggregatorFactory) DefaultDimensionSpec(io.druid.query.dimension.DefaultDimensionSpec) ExpressionPostAggregator(io.druid.query.aggregation.post.ExpressionPostAggregator) Row(io.druid.data.input.Row) MapBasedRow(io.druid.data.input.MapBasedRow) Test(org.junit.Test)

Example 2 with ExpressionPostAggregator

use of io.druid.query.aggregation.post.ExpressionPostAggregator in project druid by druid-io.

the class Expressions method toPostAggregator.

/**
   * Translate a Calcite row-expression to a Druid PostAggregator. One day, when possible, this could be folded
   * into {@link #toRowExtraction(DruidOperatorTable, PlannerContext, List, RexNode)} .
   *
   * @param name                              name of the PostAggregator
   * @param rowOrder                          order of fields in the Druid rows to be extracted from
   * @param finalizingPostAggregatorFactories post-aggregators that should be used for specific entries in rowOrder.
   *                                          May be empty, and individual values may be null. Missing or null values
   *                                          will lead to creation of {@link FieldAccessPostAggregator}.
   * @param expression                        expression meant to be applied on top of the rows
   *
   * @return PostAggregator or null if not possible
   */
public static PostAggregator toPostAggregator(final String name, final List<String> rowOrder, final List<PostAggregatorFactory> finalizingPostAggregatorFactories, final RexNode expression) {
    final PostAggregator retVal;
    if (expression.getKind() == SqlKind.INPUT_REF) {
        final RexInputRef ref = (RexInputRef) expression;
        final PostAggregatorFactory finalizingPostAggregatorFactory = finalizingPostAggregatorFactories.get(ref.getIndex());
        retVal = finalizingPostAggregatorFactory != null ? finalizingPostAggregatorFactory.factorize(name) : new FieldAccessPostAggregator(name, rowOrder.get(ref.getIndex()));
    } else if (expression.getKind() == SqlKind.CAST) {
        // Ignore CAST when translating to PostAggregators and hope for the best. They are really loosey-goosey with
        // types internally and there isn't much we can do to respect
        // TODO(gianm): Probably not a good idea to ignore CAST like this.
        final RexNode operand = ((RexCall) expression).getOperands().get(0);
        retVal = toPostAggregator(name, rowOrder, finalizingPostAggregatorFactories, operand);
    } else if (expression.getKind() == SqlKind.LITERAL && SqlTypeName.NUMERIC_TYPES.contains(expression.getType().getSqlTypeName())) {
        retVal = new ConstantPostAggregator(name, (Number) RexLiteral.value(expression));
    } else if (expression.getKind() == SqlKind.TIMES || expression.getKind() == SqlKind.DIVIDE || expression.getKind() == SqlKind.PLUS || expression.getKind() == SqlKind.MINUS) {
        final String fnName = ImmutableMap.<SqlKind, String>builder().put(SqlKind.TIMES, "*").put(SqlKind.DIVIDE, "quotient").put(SqlKind.PLUS, "+").put(SqlKind.MINUS, "-").build().get(expression.getKind());
        final List<PostAggregator> operands = Lists.newArrayList();
        for (RexNode operand : ((RexCall) expression).getOperands()) {
            final PostAggregator translatedOperand = toPostAggregator(null, rowOrder, finalizingPostAggregatorFactories, operand);
            if (translatedOperand == null) {
                return null;
            }
            operands.add(translatedOperand);
        }
        retVal = new ArithmeticPostAggregator(name, fnName, operands);
    } else {
        // Try converting to a math expression.
        final String mathExpression = Expressions.toMathExpression(rowOrder, expression);
        if (mathExpression == null) {
            retVal = null;
        } else {
            retVal = new ExpressionPostAggregator(name, mathExpression);
        }
    }
    if (retVal != null && name != null && !name.equals(retVal.getName())) {
        throw new ISE("WTF?! Was about to return a PostAggregator with bad name, [%s] != [%s]", name, retVal.getName());
    }
    return retVal;
}
Also used : ArithmeticPostAggregator(io.druid.query.aggregation.post.ArithmeticPostAggregator) FieldAccessPostAggregator(io.druid.query.aggregation.post.FieldAccessPostAggregator) ExpressionPostAggregator(io.druid.query.aggregation.post.ExpressionPostAggregator) ConstantPostAggregator(io.druid.query.aggregation.post.ConstantPostAggregator) PostAggregator(io.druid.query.aggregation.PostAggregator) FieldAccessPostAggregator(io.druid.query.aggregation.post.FieldAccessPostAggregator) ArithmeticPostAggregator(io.druid.query.aggregation.post.ArithmeticPostAggregator) ConstantPostAggregator(io.druid.query.aggregation.post.ConstantPostAggregator) PostAggregatorFactory(io.druid.sql.calcite.aggregation.PostAggregatorFactory) RexCall(org.apache.calcite.rex.RexCall) ExpressionPostAggregator(io.druid.query.aggregation.post.ExpressionPostAggregator) RexInputRef(org.apache.calcite.rex.RexInputRef) List(java.util.List) ISE(io.druid.java.util.common.ISE) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with ExpressionPostAggregator

use of io.druid.query.aggregation.post.ExpressionPostAggregator in project druid by druid-io.

the class GroupByQueryRunnerTest method testMergedPostAggHavingSpec.

@Test
public void testMergedPostAggHavingSpec() {
    List<Row> expectedResults = Arrays.asList(GroupByQueryRunnerTestHelper.createExpectedRow("2011-04-01", "alias", "business", "rows", 2L, "idx", 217L, "rows_times_10", 20.0), GroupByQueryRunnerTestHelper.createExpectedRow("2011-04-01", "alias", "mezzanine", "rows", 6L, "idx", 4420L, "rows_times_10", 60.0), GroupByQueryRunnerTestHelper.createExpectedRow("2011-04-01", "alias", "premium", "rows", 6L, "idx", 4416L, "rows_times_10", 60.0));
    GroupByQuery.Builder builder = GroupByQuery.builder().setDataSource(QueryRunnerTestHelper.dataSource).setInterval("2011-04-02/2011-04-04").setDimensions(Lists.<DimensionSpec>newArrayList(new DefaultDimensionSpec("quality", "alias"))).setAggregatorSpecs(Arrays.asList(QueryRunnerTestHelper.rowsCount, new LongSumAggregatorFactory("idx", "index"))).setPostAggregatorSpecs(Arrays.<PostAggregator>asList(new ArithmeticPostAggregator("rows_times_10", "*", Arrays.<PostAggregator>asList(new FieldAccessPostAggregator("rows", "rows"), new ConstantPostAggregator("const", 10L))))).setGranularity(new PeriodGranularity(new Period("P1M"), null, null)).setHavingSpec(new OrHavingSpec(ImmutableList.<HavingSpec>of(new GreaterThanHavingSpec("rows_times_10", 20L), new EqualToHavingSpec("idx", 217L))));
    GroupByQuery fullQuery = builder.build();
    QueryRunner mergedRunner = factory.getToolchest().mergeResults(new QueryRunner<Row>() {

        @Override
        public Sequence<Row> run(Query<Row> query, Map<String, Object> responseContext) {
            // simulate two daily segments
            final Query query1 = query.withQuerySegmentSpec(new MultipleIntervalSegmentSpec(Lists.newArrayList(new Interval("2011-04-02/2011-04-03"))));
            final Query query2 = query.withQuerySegmentSpec(new MultipleIntervalSegmentSpec(Lists.newArrayList(new Interval("2011-04-03/2011-04-04"))));
            return new MergeSequence(query.getResultOrdering(), Sequences.simple(Arrays.asList(runner.run(query1, responseContext), runner.run(query2, responseContext))));
        }
    });
    Map<String, Object> context = Maps.newHashMap();
    // add an extra layer of merging, simulate broker forwarding query to historical
    TestHelper.assertExpectedObjects(expectedResults, factory.getToolchest().postMergeQueryDecoration(factory.getToolchest().mergeResults(factory.getToolchest().preMergeQueryDecoration(mergedRunner))).run(fullQuery, context), "merged");
    fullQuery = fullQuery.withPostAggregatorSpecs(Arrays.<PostAggregator>asList(new ExpressionPostAggregator("rows_times_10", "rows * 10.0")));
    TestHelper.assertExpectedObjects(expectedResults, factory.getToolchest().postMergeQueryDecoration(factory.getToolchest().mergeResults(factory.getToolchest().preMergeQueryDecoration(mergedRunner))).run(fullQuery, context), "merged");
}
Also used : EqualToHavingSpec(io.druid.query.groupby.having.EqualToHavingSpec) ArithmeticPostAggregator(io.druid.query.aggregation.post.ArithmeticPostAggregator) Query(io.druid.query.Query) LongSumAggregatorFactory(io.druid.query.aggregation.LongSumAggregatorFactory) PeriodGranularity(io.druid.java.util.common.granularity.PeriodGranularity) MultipleIntervalSegmentSpec(io.druid.query.spec.MultipleIntervalSegmentSpec) MergeSequence(io.druid.java.util.common.guava.MergeSequence) ExpressionPostAggregator(io.druid.query.aggregation.post.ExpressionPostAggregator) GreaterThanHavingSpec(io.druid.query.groupby.having.GreaterThanHavingSpec) FieldAccessPostAggregator(io.druid.query.aggregation.post.FieldAccessPostAggregator) OrHavingSpec(io.druid.query.groupby.having.OrHavingSpec) HyperUniqueFinalizingPostAggregator(io.druid.query.aggregation.hyperloglog.HyperUniqueFinalizingPostAggregator) FieldAccessPostAggregator(io.druid.query.aggregation.post.FieldAccessPostAggregator) ExpressionPostAggregator(io.druid.query.aggregation.post.ExpressionPostAggregator) ConstantPostAggregator(io.druid.query.aggregation.post.ConstantPostAggregator) PostAggregator(io.druid.query.aggregation.PostAggregator) ArithmeticPostAggregator(io.druid.query.aggregation.post.ArithmeticPostAggregator) ConstantPostAggregator(io.druid.query.aggregation.post.ConstantPostAggregator) Period(org.joda.time.Period) Sequence(io.druid.java.util.common.guava.Sequence) MergeSequence(io.druid.java.util.common.guava.MergeSequence) DefaultDimensionSpec(io.druid.query.dimension.DefaultDimensionSpec) FinalizeResultsQueryRunner(io.druid.query.FinalizeResultsQueryRunner) QueryRunner(io.druid.query.QueryRunner) GreaterThanHavingSpec(io.druid.query.groupby.having.GreaterThanHavingSpec) HavingSpec(io.druid.query.groupby.having.HavingSpec) DimFilterHavingSpec(io.druid.query.groupby.having.DimFilterHavingSpec) BaseHavingSpec(io.druid.query.groupby.having.BaseHavingSpec) OrHavingSpec(io.druid.query.groupby.having.OrHavingSpec) DimensionSelectorHavingSpec(io.druid.query.groupby.having.DimensionSelectorHavingSpec) EqualToHavingSpec(io.druid.query.groupby.having.EqualToHavingSpec) Row(io.druid.data.input.Row) Interval(org.joda.time.Interval) Test(org.junit.Test)

Aggregations

PostAggregator (io.druid.query.aggregation.PostAggregator)3 ArithmeticPostAggregator (io.druid.query.aggregation.post.ArithmeticPostAggregator)3 ConstantPostAggregator (io.druid.query.aggregation.post.ConstantPostAggregator)3 ExpressionPostAggregator (io.druid.query.aggregation.post.ExpressionPostAggregator)3 Row (io.druid.data.input.Row)2 Sequence (io.druid.java.util.common.guava.Sequence)2 LongSumAggregatorFactory (io.druid.query.aggregation.LongSumAggregatorFactory)2 FieldAccessPostAggregator (io.druid.query.aggregation.post.FieldAccessPostAggregator)2 DefaultDimensionSpec (io.druid.query.dimension.DefaultDimensionSpec)2 Test (org.junit.Test)2 MapBasedRow (io.druid.data.input.MapBasedRow)1 ISE (io.druid.java.util.common.ISE)1 PeriodGranularity (io.druid.java.util.common.granularity.PeriodGranularity)1 MergeSequence (io.druid.java.util.common.guava.MergeSequence)1 FinalizeResultsQueryRunner (io.druid.query.FinalizeResultsQueryRunner)1 Query (io.druid.query.Query)1 QueryRunner (io.druid.query.QueryRunner)1 AggregatorFactory (io.druid.query.aggregation.AggregatorFactory)1 HyperUniqueFinalizingPostAggregator (io.druid.query.aggregation.hyperloglog.HyperUniqueFinalizingPostAggregator)1 DimensionSpec (io.druid.query.dimension.DimensionSpec)1