Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

All Filters should work with FilteredAggregators. #2711

Merged
merged 1 commit into from
Mar 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions docs/content/querying/aggregations.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,6 @@ A filtered aggregator wraps any given aggregator, but only aggregates the values

This makes it possible to compute the results of a filtered and an unfiltered aggregation simultaneously, without having to issue multiple queries, and use both results as part of post-aggregations.

*Limitations:* The filtered aggregator currently only supports 'or', 'and', 'selector', 'not' and 'Extraction' filters, i.e. matching one or multiple dimensions against a single value.

*Note:* If only the filtered results are required, consider putting the filter on the query itself, which will be much faster since it does not require scanning all the data.

```json
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,19 @@

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import io.druid.query.dimension.DefaultDimensionSpec;
import io.druid.query.filter.DimFilter;
import io.druid.query.filter.ValueMatcher;
import io.druid.query.filter.ValueMatcherFactory;
import io.druid.segment.ColumnSelectorFactory;
import io.druid.segment.DimensionSelector;
import io.druid.segment.data.IndexedInts;
import io.druid.segment.filter.BooleanValueMatcher;
import io.druid.segment.filter.Filters;

import java.nio.ByteBuffer;
import java.util.BitSet;
import java.util.Comparator;
import java.util.List;

Expand All @@ -52,18 +59,19 @@ public FilteredAggregatorFactory(
@Override
public Aggregator factorize(ColumnSelectorFactory columnSelectorFactory)
{
final ValueMatcher valueMatcher = Filters.convertDimensionFilters(filter).makeMatcher(columnSelectorFactory);
return new FilteredAggregator(
valueMatcher,
delegate.factorize(columnSelectorFactory)
);

final ValueMatcherFactory valueMatcherFactory = new FilteredAggregatorValueMatcherFactory(columnSelectorFactory);
final ValueMatcher valueMatcher = Filters.convertDimensionFilters(filter).makeMatcher(valueMatcherFactory);
return new FilteredAggregator(
valueMatcher,
delegate.factorize(columnSelectorFactory)
);
}

@Override
public BufferAggregator factorizeBuffered(ColumnSelectorFactory columnSelectorFactory)
{
final ValueMatcher valueMatcher = Filters.convertDimensionFilters(filter).makeMatcher(columnSelectorFactory);
final ValueMatcherFactory valueMatcherFactory = new FilteredAggregatorValueMatcherFactory(columnSelectorFactory);
final ValueMatcher valueMatcher = Filters.convertDimensionFilters(filter).makeMatcher(valueMatcherFactory);
return new FilteredBufferAggregator(
valueMatcher,
delegate.factorizeBuffered(columnSelectorFactory)
Expand Down Expand Up @@ -199,4 +207,85 @@ public int hashCode()
result = 31 * result + (filter != null ? filter.hashCode() : 0);
return result;
}

private static class FilteredAggregatorValueMatcherFactory implements ValueMatcherFactory
{
private final ColumnSelectorFactory columnSelectorFactory;

public FilteredAggregatorValueMatcherFactory(ColumnSelectorFactory columnSelectorFactory)
{
this.columnSelectorFactory = columnSelectorFactory;
}

@Override
public ValueMatcher makeValueMatcher(final String dimension, final Comparable value)
{
final DimensionSelector selector = columnSelectorFactory.makeDimensionSelector(
new DefaultDimensionSpec(dimension, dimension)
);

// Compare "value" as a String.
final String valueString = value == null ? null : value.toString();
final boolean isNullOrEmpty = valueString == null || valueString.isEmpty();

// Missing columns match a null or empty string value, and don't match anything else.
if (selector == null) {
return new BooleanValueMatcher(isNullOrEmpty);
}

final int valueId = selector.lookupId(valueString);
return new ValueMatcher()
{
@Override
public boolean matches()
{
final IndexedInts row = selector.getRow();
final int size = row.size();
for (int i = 0; i < size; ++i) {
if (row.get(i) == valueId) {
return true;
}
}
return false;
}
};
}

@Override
public ValueMatcher makeValueMatcher(final String dimension, final Predicate predicate)
{
final DimensionSelector selector = columnSelectorFactory.makeDimensionSelector(
new DefaultDimensionSpec(dimension, dimension)
);

if (selector == null) {
return new BooleanValueMatcher(predicate.apply(null));
}

// Check every value in the dimension, as a String.
final int cardinality = selector.getValueCardinality();
final BitSet valueIds = new BitSet(cardinality);
for (int i = 0; i < cardinality; i++) {
if (predicate.apply(selector.lookupName(i))) {
valueIds.set(i);
}
}

return new ValueMatcher()
{
@Override
public boolean matches()
{
final IndexedInts row = selector.getRow();
final int size = row.size();
for (int i = 0; i < size; ++i) {
if (valueIds.get(row.get(i))) {
return true;
}
}
return false;
}
};
}
}
}
2 changes: 0 additions & 2 deletions processing/src/main/java/io/druid/query/filter/Filter.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,11 @@
package io.druid.query.filter;

import com.metamx.collections.bitmap.ImmutableBitmap;
import io.druid.segment.ColumnSelectorFactory;

/**
*/
public interface Filter
{
public ImmutableBitmap getBitmapIndex(BitmapIndexSelector selector);
public ValueMatcher makeMatcher(ValueMatcherFactory factory);
public ValueMatcher makeMatcher(ColumnSelectorFactory columnSelectorFactory);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,11 @@
package io.druid.query.filter;

import com.google.common.base.Predicate;
import com.metamx.collections.spatial.search.Bound;

/**
*/
public interface ValueMatcherFactory
{
public ValueMatcher makeValueMatcher(String dimension, Comparable value);
public ValueMatcher makeValueMatcher(String dimension, Predicate value);
public ValueMatcher makeValueMatcher(String dimension, Bound bound);
public ValueMatcher makeValueMatcher(String dimension, Predicate predicate);
}
11 changes: 0 additions & 11 deletions processing/src/main/java/io/druid/segment/filter/AndFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import io.druid.query.filter.Filter;
import io.druid.query.filter.ValueMatcher;
import io.druid.query.filter.ValueMatcherFactory;
import io.druid.segment.ColumnSelectorFactory;

import java.util.List;

Expand Down Expand Up @@ -72,16 +71,6 @@ public ValueMatcher makeMatcher(ValueMatcherFactory factory)
return makeMatcher(matchers);
}

public ValueMatcher makeMatcher(ColumnSelectorFactory factory)
{
final ValueMatcher[] matchers = new ValueMatcher[filters.size()];

for (int i = 0; i < filters.size(); i++) {
matchers[i] = filters.get(i).makeMatcher(factory);
}
return makeMatcher(matchers);
}

private ValueMatcher makeMatcher(final ValueMatcher[] baseMatchers)
{
if (baseMatchers.length == 1) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import io.druid.query.filter.Filter;
import io.druid.query.filter.ValueMatcher;
import io.druid.query.filter.ValueMatcherFactory;
import io.druid.segment.ColumnSelectorFactory;
import io.druid.segment.data.Indexed;

import javax.annotation.Nullable;
Expand Down Expand Up @@ -77,10 +76,4 @@ public ValueMatcher makeMatcher(ValueMatcherFactory factory)
{
return factory.makeValueMatcher(dimension, predicate);
}

@Override
public ValueMatcher makeMatcher(ColumnSelectorFactory factory)
{
throw new UnsupportedOperationException();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,13 @@
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.metamx.collections.bitmap.ImmutableBitmap;
import io.druid.query.dimension.DefaultDimensionSpec;
import io.druid.query.extraction.ExtractionFn;
import io.druid.query.filter.BitmapIndexSelector;
import io.druid.query.filter.Filter;
import io.druid.query.filter.ValueMatcher;
import io.druid.query.filter.ValueMatcherFactory;
import io.druid.segment.ColumnSelectorFactory;
import io.druid.segment.DimensionSelector;
import io.druid.segment.data.Indexed;
import io.druid.segment.data.IndexedInts;

import java.util.BitSet;
import java.util.Iterator;
import java.util.List;

Expand Down Expand Up @@ -121,38 +116,4 @@ public boolean apply(String input)
}
);
}

@Override
public ValueMatcher makeMatcher(ColumnSelectorFactory columnSelectorFactory)
{
final DimensionSelector dimensionSelector = columnSelectorFactory.makeDimensionSelector(
new DefaultDimensionSpec(dimension, dimension)
);
if (dimensionSelector == null) {
return new BooleanValueMatcher(value.equals(Strings.nullToEmpty(fn.apply(null))));
} else {
final BitSet bitSetOfIds = new BitSet(dimensionSelector.getValueCardinality());
for (int i = 0; i < dimensionSelector.getValueCardinality(); i++) {
if (value.equals(Strings.nullToEmpty(fn.apply(dimensionSelector.lookupName(i))))) {
bitSetOfIds.set(i);
}
}
return new ValueMatcher()
{
@Override
public boolean matches()
{
final IndexedInts row = dimensionSelector.getRow();
final int size = row.size();
for (int i = 0; i < size; ++i) {
if (bitSetOfIds.get(row.get(i))) {
return true;
}
}
return false;
}
};
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import io.druid.query.filter.Filter;
import io.druid.query.filter.ValueMatcher;
import io.druid.query.filter.ValueMatcherFactory;
import io.druid.segment.ColumnSelectorFactory;
import io.druid.segment.data.Indexed;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
Expand Down Expand Up @@ -161,11 +160,4 @@ public int hashCode()
return script.hashCode();
}
}

@Override
public ValueMatcher makeMatcher(ColumnSelectorFactory factory)
{
throw new UnsupportedOperationException();
}

}
16 changes: 0 additions & 16 deletions processing/src/main/java/io/druid/segment/filter/NotFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import io.druid.query.filter.Filter;
import io.druid.query.filter.ValueMatcher;
import io.druid.query.filter.ValueMatcherFactory;
import io.druid.segment.ColumnSelectorFactory;

/**
*/
Expand Down Expand Up @@ -62,19 +61,4 @@ public boolean matches()
}
};
}

@Override
public ValueMatcher makeMatcher(ColumnSelectorFactory factory)
{
final ValueMatcher baseMatcher = baseFilter.makeMatcher(factory);

return new ValueMatcher()
{
@Override
public boolean matches()
{
return !baseMatcher.matches();
}
};
}
}
11 changes: 0 additions & 11 deletions processing/src/main/java/io/druid/segment/filter/OrFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import io.druid.query.filter.Filter;
import io.druid.query.filter.ValueMatcher;
import io.druid.query.filter.ValueMatcherFactory;
import io.druid.segment.ColumnSelectorFactory;

import java.util.List;

Expand Down Expand Up @@ -72,16 +71,6 @@ public ValueMatcher makeMatcher(ValueMatcherFactory factory)
return makeMatcher(matchers);
}

public ValueMatcher makeMatcher(ColumnSelectorFactory factory)
{
final ValueMatcher[] matchers = new ValueMatcher[filters.size()];

for (int i = 0; i < filters.size(); i++) {
matchers[i] = filters.get(i).makeMatcher(factory);
}
return makeMatcher(matchers);
}

private ValueMatcher makeMatcher(final ValueMatcher[] baseMatchers){
if (baseMatchers.length == 1) {
return baseMatchers[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,11 @@

package io.druid.segment.filter;

import com.google.common.base.Strings;
import com.metamx.collections.bitmap.ImmutableBitmap;
import io.druid.query.dimension.DefaultDimensionSpec;
import io.druid.query.filter.BitmapIndexSelector;
import io.druid.query.filter.Filter;
import io.druid.query.filter.ValueMatcher;
import io.druid.query.filter.ValueMatcherFactory;
import io.druid.segment.ColumnSelectorFactory;
import io.druid.segment.DimensionSelector;
import io.druid.segment.data.IndexedInts;

/**
*/
Expand Down Expand Up @@ -57,36 +52,4 @@ public ValueMatcher makeMatcher(ValueMatcherFactory factory)
{
return factory.makeValueMatcher(dimension, value);
}

@Override
public ValueMatcher makeMatcher(ColumnSelectorFactory columnSelectorFactory)
{
final DimensionSelector dimensionSelector = columnSelectorFactory.makeDimensionSelector(
new DefaultDimensionSpec(dimension, dimension)
);

// Missing columns match a null or empty string value and don't match anything else
if (dimensionSelector == null) {
return new BooleanValueMatcher(Strings.isNullOrEmpty(value));
} else {
final int valueId = dimensionSelector.lookupId(value);
return new ValueMatcher()
{
@Override
public boolean matches()
{
final IndexedInts row = dimensionSelector.getRow();
final int size = row.size();
for (int i = 0; i < size; ++i) {
if (row.get(i) == valueId) {
return true;
}
}
return false;
}
};
}
}


}
Loading