Skip to content

Commit

Permalink
Merge pull request #1712 from metamx/searchQueryDimExtraction
Browse files Browse the repository at this point in the history
Add dimension extraction functionality to SearchQuery
  • Loading branch information
xvrl committed Sep 14, 2015
2 parents 5ff9266 + e569f4b commit 5f36e7a
Show file tree
Hide file tree
Showing 11 changed files with 360 additions and 73 deletions.
74 changes: 51 additions & 23 deletions processing/src/main/java/io/druid/query/Druids.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,22 @@

package io.druid.query;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import io.druid.granularity.QueryGranularity;
import io.druid.query.aggregation.AggregatorFactory;
import io.druid.query.aggregation.PostAggregator;
import io.druid.query.datasourcemetadata.DataSourceMetadataQuery;
import io.druid.query.dimension.DefaultDimensionSpec;
import io.druid.query.dimension.DimensionSpec;
import io.druid.query.filter.AndDimFilter;
import io.druid.query.filter.DimFilter;
import io.druid.query.filter.NoopDimFilter;
import io.druid.query.filter.NotDimFilter;
import io.druid.query.filter.OrDimFilter;
import io.druid.query.filter.SelectorDimFilter;
import io.druid.query.datasourcemetadata.DataSourceMetadataQuery;
import io.druid.query.metadata.metadata.ColumnIncluderator;
import io.druid.query.metadata.metadata.SegmentMetadataQuery;
import io.druid.query.search.SearchResultValue;
Expand All @@ -44,13 +49,24 @@
import org.joda.time.DateTime;
import org.joda.time.Interval;

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

/**
*/
public class Druids
{
public static final Function<String, DimensionSpec> DIMENSION_IDENTITY = new Function<String, DimensionSpec>()
{
@Nullable
@Override
public DimensionSpec apply(String input)
{
return new DefaultDimensionSpec(input, input);
}
};

private Druids()
{
throw new AssertionError();
Expand All @@ -60,7 +76,7 @@ private Druids()
* A Builder for AndDimFilter.
*
* Required: fields() must be called before build()
*
*
* Usage example:
* <pre><code>
* AndDimFilter andDimFilter = Druids.newAndDimFilterBuilder()
Expand Down Expand Up @@ -104,9 +120,9 @@ public static AndDimFilterBuilder newAndDimFilterBuilder()

/**
* A Builder for OrDimFilter.
*
*
* Required: fields() must be called before build()
*
*
* Usage example:
* <pre><code>
* OrDimFilter orDimFilter = Druids.newOrDimFilterBuilder()
Expand Down Expand Up @@ -159,9 +175,9 @@ public static OrDimFilterBuilder newOrDimFilterBuilder()

/**
* A Builder for NotDimFilter.
*
*
* Required: field() must be called before build()
*
*
* Usage example:
* <pre><code>
* NotDimFilter notDimFilter = Druids.newNotDimFilterBuilder()
Expand Down Expand Up @@ -205,9 +221,9 @@ public static NotDimFilterBuilder newNotDimFilterBuilder()

/**
* A Builder for SelectorDimFilter.
*
*
* Required: dimension() and value() must be called before build()
*
*
* Usage example:
* <pre><code>
* Selector selDimFilter = Druids.newSelectorDimFilterBuilder()
Expand Down Expand Up @@ -284,10 +300,10 @@ public static NoopDimFilterBuilder newNoopDimFilterBuilder()

/**
* A Builder for TimeseriesQuery.
*
*
* Required: dataSource(), intervals(), and aggregators() must be called before build()
* Optional: filters(), granularity(), postAggregators(), and context() can be called before build()
*
*
* Usage example:
* <pre><code>
* TimeseriesQuery query = Druids.newTimeseriesQueryBuilder()
Expand Down Expand Up @@ -482,11 +498,11 @@ public static TimeseriesQueryBuilder newTimeseriesQueryBuilder()

/**
* A Builder for SearchQuery.
*
*
* Required: dataSource(), intervals(), dimensions() and query() must be called before build()
*
*
* Optional: filters(), granularity(), and context() can be called before build()
*
*
* Usage example:
* <pre><code>
* SearchQuery query = Druids.newSearchQueryBuilder()
Expand All @@ -506,7 +522,7 @@ public static class SearchQueryBuilder
private QueryGranularity granularity;
private int limit;
private QuerySegmentSpec querySegmentSpec;
private List<String> dimensions;
private List<DimensionSpec> dimensions;
private SearchQuerySpec querySpec;
private Map<String, Object> context;

Expand Down Expand Up @@ -634,12 +650,24 @@ public SearchQueryBuilder intervals(List<Interval> l)
}

public SearchQueryBuilder dimensions(String d)
{
dimensions = ImmutableList.of(DIMENSION_IDENTITY.apply(d));
return this;
}

public SearchQueryBuilder dimensions(Iterable<String> d)
{
dimensions = ImmutableList.copyOf(Iterables.transform(d, DIMENSION_IDENTITY));
return this;
}

public SearchQueryBuilder dimensions(DimensionSpec d)
{
dimensions = Lists.newArrayList(d);
return this;
}

public SearchQueryBuilder dimensions(List<String> d)
public SearchQueryBuilder dimensions(List<DimensionSpec> d)
{
dimensions = d;
return this;
Expand Down Expand Up @@ -677,9 +705,9 @@ public static SearchQueryBuilder newSearchQueryBuilder()

/**
* A Builder for TimeBoundaryQuery.
*
*
* Required: dataSource() must be called before build()
*
*
* Usage example:
* <pre><code>
* TimeBoundaryQuery query = new MaxTimeQueryBuilder()
Expand Down Expand Up @@ -773,9 +801,9 @@ public static TimeBoundaryQueryBuilder newTimeBoundaryQueryBuilder()

/**
* A Builder for Result.
*
*
* Required: timestamp() and value() must be called before build()
*
*
* Usage example:
* <pre><code>
* Result&lt;T&gt; result = Druids.newResultBuilder()
Expand Down Expand Up @@ -839,9 +867,9 @@ public static ResultBuilder<TimeBoundaryResultValue> newTimeBoundaryResultBuilde

/**
* A Builder for SegmentMetadataQuery.
*
*
* Required: dataSource(), intervals() must be called before build()
*
*
* Usage example:
* <pre><code>
* SegmentMetadataQuery query = new SegmentMetadataQueryBuilder()
Expand Down Expand Up @@ -947,9 +975,9 @@ public static SegmentMetadataQueryBuilder newSegmentMetadataQueryBuilder()

/**
* A Builder for SelectQuery.
*
*
* Required: dataSource(), intervals() must be called before build()
*
*
* Usage example:
* <pre><code>
* SelectQuery query = new SelectQueryBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
@JsonSubTypes.Type(name = "searchQuery", value = SearchQuerySpecDimExtractionFn.class),
@JsonSubTypes.Type(name = "javascript", value = JavascriptExtractionFn.class),
@JsonSubTypes.Type(name = "timeFormat", value = TimeFormatExtractionFn.class),
@JsonSubTypes.Type(name = "lookup", value = LookupExtractionFn.class)
@JsonSubTypes.Type(name = "lookup", value = LookupExtractionFn.class),
@JsonSubTypes.Type(name = "identity", value = IdentityExtractionFn.class)
})
/**
* An ExtractionFn is a function that can be used to transform the values of a column (typically a dimension)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Metamarkets licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

package io.druid.query.extraction;

import com.google.common.base.Strings;

public class IdentityExtractionFn implements ExtractionFn
{
private static final byte CACHE_TYPE_ID = 0x6;
@Override
public byte[] getCacheKey()
{
return new byte[]{CACHE_TYPE_ID};
}

@Override
public String apply(Object value)
{
return value == null ? null : Strings.emptyToNull(value.toString());
}

@Override
public String apply(String value)
{
return Strings.emptyToNull(value);
}

@Override
public String apply(long value)
{
return Long.toString(value);
}

@Override
public boolean preservesOrdering()
{
return true;
}

@Override
public ExtractionType getExtractionType()
{
return ExtractionType.ONE_TO_ONE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.base.Function;
import com.google.common.base.Functions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.google.common.primitives.Ints;
import com.google.inject.Inject;
import com.metamx.common.IAE;
Expand All @@ -32,19 +32,19 @@
import com.metamx.common.guava.Sequence;
import com.metamx.common.guava.Sequences;
import com.metamx.common.guava.nary.BinaryFn;
import com.metamx.common.StringUtils;
import com.metamx.emitter.service.ServiceMetricEvent;
import io.druid.collections.OrderedMergeSequence;
import io.druid.query.CacheStrategy;
import io.druid.query.DruidMetrics;
import io.druid.query.IntervalChunkingQueryRunnerDecorator;
import io.druid.query.Query;
import io.druid.query.DruidMetrics;
import io.druid.query.QueryRunner;
import io.druid.query.QueryToolChest;
import io.druid.query.Result;
import io.druid.query.ResultGranularTimestampComparator;
import io.druid.query.ResultMergeQueryRunner;
import io.druid.query.aggregation.MetricManipulationFn;
import io.druid.query.dimension.DimensionSpec;
import io.druid.query.filter.DimFilter;
import io.druid.query.search.search.SearchHit;
import io.druid.query.search.search.SearchQuery;
Expand All @@ -53,9 +53,9 @@

import javax.annotation.Nullable;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
*/
Expand Down Expand Up @@ -152,16 +152,15 @@ public byte[] computeCacheKey(SearchQuery query)
final byte[] querySpecBytes = query.getQuery().getCacheKey();
final byte[] granularityBytes = query.getGranularity().cacheKey();

final Set<String> dimensions = Sets.newTreeSet();
if (query.getDimensions() != null) {
dimensions.addAll(query.getDimensions());
}
final Collection<DimensionSpec> dimensions = query.getDimensions() == null
? ImmutableList.<DimensionSpec>of()
: query.getDimensions();

final byte[][] dimensionsBytes = new byte[dimensions.size()][];
int dimensionsBytesSize = 0;
int index = 0;
for (String dimension : dimensions) {
dimensionsBytes[index] = StringUtils.toUtf8(dimension);
for (DimensionSpec dimension : dimensions) {
dimensionsBytes[index] = dimension.getCacheKey();
dimensionsBytesSize += dimensionsBytes[index].length;
++index;
}
Expand Down Expand Up @@ -215,7 +214,7 @@ public Result<SearchResultValue> apply(Object input)
List<Object> result = (List<Object>) input;

return new Result<>(
new DateTime(((Number)result.get(0)).longValue()),
new DateTime(((Number) result.get(0)).longValue()),
new SearchResultValue(
Lists.transform(
(List) result.get(1),
Expand Down
Loading

0 comments on commit 5f36e7a

Please sign in to comment.