io.druid.query.count.FrequencyCountQueryQueryToolChest.java Source code

Java tutorial

Introduction

Here is the source code for io.druid.query.count.FrequencyCountQueryQueryToolChest.java

Source

/*
 * Druid - a distributed column store.
 * Copyright (C) 2012  Metamarkets Group Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package io.druid.query.count;

import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.metamx.common.JodaUtils;
import com.metamx.common.guava.Sequence;
import com.metamx.common.guava.nary.BinaryFn;
import com.metamx.emitter.service.ServiceMetricEvent;
import io.druid.collections.OrderedMergeSequence;
import io.druid.query.Query;
import io.druid.query.QueryRunner;
import io.druid.query.QueryToolChest;
import io.druid.query.ResultGranularTimestampComparator;
import io.druid.query.ResultMergeQueryRunner;
import io.druid.query.Result;
import io.druid.query.aggregation.MetricManipulationFn;
import org.joda.time.Interval;
import org.joda.time.Minutes;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class FrequencyCountQueryQueryToolChest
        extends QueryToolChest<Result<FrequencyCountResult>, FrequencyCountQuery> {
    private static final TypeReference<Result<FrequencyCountResult>> TYPE_REFERENCE = new TypeReference<Result<FrequencyCountResult>>() {
    };

    @Override
    public QueryRunner<Result<FrequencyCountResult>> mergeResults(
            final QueryRunner<Result<FrequencyCountResult>> runner) {
        return new ResultMergeQueryRunner<Result<FrequencyCountResult>>(runner) {
            @Override
            protected Ordering<Result<FrequencyCountResult>> makeOrdering(
                    Query<Result<FrequencyCountResult>> query) {
                return getOrdering();
                /* TODO not sure above works
                return Ordering.from(
                    new ResultGranularTimestampComparator<FrequencyCountResult>(
                        ((FrequencyCountQuery) query).getGranularity()
                    )
                );
                */
            }

            @Override
            protected BinaryFn<Result<FrequencyCountResult>, Result<FrequencyCountResult>, Result<FrequencyCountResult>> createMergeFn(
                    final Query<Result<FrequencyCountResult>> inQ) {
                return new BinaryFn<Result<FrequencyCountResult>, Result<FrequencyCountResult>, Result<FrequencyCountResult>>() {
                    private final FrequencyCountQuery query = (FrequencyCountQuery) inQ;

                    @Override
                    public Result<FrequencyCountResult> apply(Result<FrequencyCountResult> arg1,
                            Result<FrequencyCountResult> arg2) {
                        if (arg1 == null) {
                            return arg2;
                        }

                        if (arg2 == null) {
                            return arg1;
                        }

                        FrequencyCountResult arg1Val = arg1.getValue();
                        FrequencyCountResult arg2Val = arg2.getValue();

                        /*  TODO doublecheck the merge
                        if (!query.isMerge()) {
                          throw new ISE("Merging when a merge isn't supposed to happen[%s], [%s]", arg1, arg2);
                        }
                        */

                        /*
                        List<Interval> newIntervals = JodaUtils.condenseIntervals(
                                Iterables.concat(arg1Val.getIntervals(), arg2Val.getIntervals())
                        );
                        */

                        final Map<String, Integer> leftColumns = arg1Val.getDimensionCounts();
                        final Map<String, Integer> rightColumns = arg2Val.getDimensionCounts();
                        Map<String, Integer> columns = Maps.newTreeMap();

                        Set<String> rightColumnNames = Sets.newHashSet(rightColumns.keySet());
                        for (Map.Entry<String, Integer> entry : leftColumns.entrySet()) {
                            final String columnName = entry.getKey();
                            // Merge by adding the counts together.
                            Integer right = rightColumns.get(columnName);
                            columns.put(columnName, entry.getValue() + ((right == null) ? 0 : right));
                            rightColumnNames.remove(columnName);
                        }

                        for (String columnName : rightColumnNames) {
                            columns.put(columnName, rightColumns.get(columnName));
                        }

                        return new Result<FrequencyCountResult>(arg1.getTimestamp(),
                                new FrequencyCountResult("merged", columns));
                    }
                };
            }
        };
    }

    @Override
    public Sequence<Result<FrequencyCountResult>> mergeSequences(
            Sequence<Sequence<Result<FrequencyCountResult>>> seqOfSequences) {
        return new OrderedMergeSequence<Result<FrequencyCountResult>>(getOrdering(), seqOfSequences);
    }

    @Override
    public ServiceMetricEvent.Builder makeMetricBuilder(FrequencyCountQuery query) {
        int numMinutes = 0;
        for (Interval interval : query.getIntervals()) {
            numMinutes += Minutes.minutesIn(interval).getMinutes();
        }

        return new ServiceMetricEvent.Builder().setUser2(query.getDataSource()).setUser4(query.getType())
                .setUser5(Joiner.on(",").join(query.getIntervals())).setUser6(String.valueOf(query.hasFilters()))
                .setUser7(String.valueOf(query.hasFilters())).setUser9(Minutes.minutes(numMinutes).toString());
    }

    @Override
    public Function<Result<FrequencyCountResult>, Result<FrequencyCountResult>> makeMetricManipulatorFn(
            FrequencyCountQuery query, MetricManipulationFn fn) {
        return Functions.identity();
    }

    @Override
    public TypeReference<Result<FrequencyCountResult>> getResultTypeReference() {
        return TYPE_REFERENCE;
    }

    public Ordering<Result<FrequencyCountResult>> getOrdering() {
        return Ordering.natural();
    }
}