-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Support multi-dimensional filters #2217
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| /* | ||
| * 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.cache; | ||
|
|
||
| /** | ||
| */ | ||
| public interface Cacheable | ||
| { | ||
| byte[] getCacheKey(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| /* | ||
| * 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.collections; | ||
|
|
||
| import java.lang.reflect.Array; | ||
| import java.util.Arrays; | ||
| import java.util.BitSet; | ||
| import java.util.Iterator; | ||
|
|
||
| /** | ||
| */ | ||
| public class IterableUtils | ||
| { | ||
| // simple cartesian iterable | ||
| public static Iterable<Object[]> cartesian(final Iterable... iterables) | ||
| { | ||
| return cartesian(Object.class, iterables); | ||
| } | ||
|
|
||
| @SafeVarargs | ||
| public static <T> Iterable<T[]> cartesian(final Class<T> clazz, final Iterable<T>... iterables) | ||
| { | ||
| return new Iterable<T[]>() | ||
| { | ||
| @Override | ||
| public Iterator<T[]> iterator() | ||
| { | ||
| return new Iterator<T[]>() | ||
| { | ||
| private final Iterator<T>[] iterators = new Iterator[iterables.length]; | ||
|
|
||
| private final T[] cached = (T[]) Array.newInstance(clazz, iterables.length); | ||
| private final BitSet valid = new BitSet(iterables.length); | ||
|
|
||
| @Override | ||
| public boolean hasNext() | ||
| { | ||
| return hasNext(0); | ||
| } | ||
|
|
||
| private boolean hasNext(int index) | ||
| { | ||
| if (iterators[index] == null) { | ||
| iterators[index] = iterables[index].iterator(); | ||
| } | ||
| for (; hasMore(index); valid.clear(index)) { | ||
| if (index == iterables.length - 1 || hasNext(index + 1)) { | ||
| return true; | ||
| } | ||
| } | ||
| iterators[index] = null; | ||
| return false; | ||
| } | ||
|
|
||
| private boolean hasMore(int index) | ||
| { | ||
| return valid.get(index) || iterators[index].hasNext(); | ||
| } | ||
|
|
||
| @Override | ||
| public T[] next() | ||
| { | ||
| for (int index = 0; index < iterables.length; index++) { | ||
| if (!valid.get(index)) { | ||
| cached[index] = iterators[index].next(); | ||
| valid.set(index); | ||
| } | ||
| } | ||
| T[] result = Arrays.copyOf(cached, cached.length); | ||
| valid.clear(cached.length - 1); | ||
| return result; | ||
| } | ||
|
|
||
| @Override | ||
| public void remove() | ||
| { | ||
| throw new UnsupportedOperationException("remove"); | ||
| } | ||
| }; | ||
| } | ||
| }; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| /* | ||
| * 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.collections; | ||
|
|
||
| import com.google.common.collect.ImmutableSet; | ||
| import com.google.common.collect.Sets; | ||
| import org.junit.Assert; | ||
| import org.junit.Test; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.Iterator; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
|
|
||
| /** | ||
| */ | ||
| public class IterableUtilsTest | ||
| { | ||
| @Test | ||
| public void testBasic() throws Exception | ||
| { | ||
| Set[] sets = { | ||
| ImmutableSet.of("A", "B"), | ||
| ImmutableSet.of("1", "2", "3"), | ||
| ImmutableSet.of("x", "y") | ||
| }; | ||
|
|
||
| Iterable<List<String>> expected = Sets.cartesianProduct(Arrays.<Set<String>>asList(sets)); | ||
| Iterable<String[]> result = IterableUtils.cartesian(String.class, sets); | ||
| for (String[] x : result) { | ||
| System.out.println("> " + Arrays.toString(x)); | ||
| } | ||
|
|
||
| Iterator<List<String>> e = expected.iterator(); | ||
| Iterator<String[]> r = result.iterator(); | ||
| while (e.hasNext() && r.hasNext()) { | ||
| Assert.assertEquals(String.valueOf(e.next()), Arrays.toString(r.next())); | ||
| } | ||
| Assert.assertFalse(e.hasNext() || r.hasNext()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,18 +63,28 @@ The filter specified at field can be any other filter defined on this page. | |
|
|
||
| ### JavaScript filter | ||
|
|
||
| The JavaScript filter matches a dimension against the specified JavaScript function predicate. The filter matches values for which the function returns true. | ||
| The JavaScript filter matches dimensions against the specified JavaScript function predicate. The filter matches values for which the function returns true. | ||
|
|
||
| The function takes a single argument, the dimension value, and returns either true or false. | ||
| The function takes same number of arguments as the dimension values, and returns either true or false. | ||
|
|
||
| ```json | ||
| { | ||
| "type" : "javascript", | ||
| "dimension" : <dimension_string>, | ||
| "function" : "function(value) { <...> }" | ||
| "dimension" : <a dimension_string>, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if this goes into 0.9.0 (which I think it should), we can make the backwards incompatible API change
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we need to maintain backwards compatibility to allow for rolling upgrades.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @xvrl is correct. I didn't think about rolling upgrades. But we can remove "dimension" from the docs and let new people use "dimensions" everywhere
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @navis let's remove "dimension" from the docs but keep it in the code
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 for removing |
||
| "dimensions" : <array of dimension_strings>, | ||
| "function" : "function(value1, value2, ...) { <...> }" | ||
| "byRow" : "false" | ||
| } | ||
| ``` | ||
|
|
||
| |property|description|required?| | ||
| |--------|-----------|---------| | ||
| |type|This String should always be "javascript".|yes| | ||
| |dimension|The dimension to perform the search over.|either of dimension or dimensions| | ||
| |dimensions|The dimensions to perform the search over.|either of dimension or dimensions| | ||
| |function|A JSON function to be applied.|yes| | ||
| |byRow|If this is true, multi-valued column is handed over as single object array to function. In this case, bitmap index cannot be applied. Default: false.|no| | ||
|
|
||
| **Example** | ||
| The following matches any dimension values for the dimension `name` between `'bar'` and `'foo'` | ||
|
|
||
|
|
@@ -86,6 +96,16 @@ The following matches any dimension values for the dimension `name` between `'ba | |
| } | ||
| ``` | ||
|
|
||
| The following matches rows where the values for the given two dimensions dim1 and dim2 are the same. | ||
| ```json | ||
| { | ||
| "type" : "javascript", | ||
| "dimensions" : ["dim1","dim2"], | ||
| "function" : "function(x, y) { return x === y }", | ||
| "byRow" : "true" | ||
| } | ||
| ``` | ||
|
|
||
| The JavaScript filter supports the use of extraction functions, see [Filtering with Extraction Functions](#filtering-with-extraction-functions) for details. | ||
|
|
||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we set some UTs for this function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done