Merge pull request #2008 from codingwhatever/regex-search-query

Regex search query
This commit is contained in:
Himanshu 2015-12-03 09:57:34 -06:00
commit 0eab8417cb
4 changed files with 170 additions and 1 deletions

View File

@ -40,4 +40,16 @@ If any part of a dimension value contains the value specified in this search que
"case_sensitive" : true,
"value" : "some_value"
}
```
RegexSearchQuerySpec
----------------------------------
If any part of a dimension value contains the pattern specified in this search query spec, a "match" occurs. The grammar is:
```json
{
"type" : "regex",
"pattern" : "some_pattern"
}
```

View File

@ -0,0 +1,104 @@
/*
* 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.search.search;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Preconditions;
import com.metamx.common.StringUtils;
import java.nio.ByteBuffer;
import java.util.regex.Pattern;
public class RegexSearchQuerySpec implements SearchQuerySpec
{
private static final byte CACHE_TYPE_ID = 0x3;
private final String pattern;
private final Pattern compiled;
@JsonCreator
public RegexSearchQuerySpec(
@JsonProperty("pattern") String pattern
)
{
this.pattern = Preconditions.checkNotNull(pattern, "pattern should not be null");
compiled = Pattern.compile(pattern);
}
@JsonProperty
public String getPattern()
{
return pattern;
}
@Override
public boolean equals(Object o)
{
if (this == o) {
return true;
}
if (!(o instanceof RegexSearchQuerySpec)) {
return false;
}
RegexSearchQuerySpec that = (RegexSearchQuerySpec) o;
return pattern.equals(that.pattern);
}
@Override
public int hashCode()
{
return pattern.hashCode();
}
@Override
public boolean accept(String dimVal)
{
if (dimVal == null) {
return false;
}
return compiled.matcher(dimVal).find();
}
@Override
public byte[] getCacheKey()
{
byte[] patternBytes = StringUtils.toUtf8(pattern);
return ByteBuffer.allocate(1 + patternBytes.length)
.put(CACHE_TYPE_ID)
.put(patternBytes)
.array();
}
@Override
public String toString()
{
return "RegexSearchQuerySpec{" +
"pattern=" + pattern + "}";
}
}

View File

@ -26,7 +26,8 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
@JsonSubTypes(value = {
@JsonSubTypes.Type(name = "contains", value = ContainsSearchQuerySpec.class),
@JsonSubTypes.Type(name = "insensitive_contains", value = InsensitiveContainsSearchQuerySpec.class),
@JsonSubTypes.Type(name = "fragment", value = FragmentSearchQuerySpec.class)
@JsonSubTypes.Type(name = "fragment", value = FragmentSearchQuerySpec.class),
@JsonSubTypes.Type(name = "regex", value = RegexSearchQuerySpec.class)
})
public interface SearchQuerySpec
{

View File

@ -0,0 +1,52 @@
/*
* 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.search;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.druid.jackson.DefaultObjectMapper;
import io.druid.query.search.search.RegexSearchQuerySpec;
import org.junit.Assert;
import org.junit.Test;
import java.io.IOException;
public class RegexSearchQueryTest
{
private static final ObjectMapper jsonMapper = new DefaultObjectMapper();
@Test
public void testQuerySerialization() throws IOException
{
RegexSearchQuerySpec spec = new RegexSearchQuerySpec("(upfront|total_market)");
String json = jsonMapper.writeValueAsString(spec);
RegexSearchQuerySpec serdeQuery = (RegexSearchQuerySpec) jsonMapper.readValue(json, RegexSearchQuerySpec.class);
Assert.assertEquals(spec, serdeQuery);
}
@Test
public void testRegexCompare()
{
RegexSearchQuerySpec rsq = new RegexSearchQuerySpec("^a.*b");
Assert.assertTrue(rsq.accept("aabb"));
Assert.assertFalse(rsq.accept("babba"));
}
}