Skip to content

Commit 08989e7

Browse files
author
Christoph Büscher
committed
Add brute force regex query support
1 parent 397a7c0 commit 08989e7

File tree

2 files changed

+84
-11
lines changed

2 files changed

+84
-11
lines changed

x-pack/plugin/versionfield/src/main/java/org/elasticsearch/xpack/versionfield/VersionStringFieldMapper.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@
1111
import org.apache.lucene.document.FieldType;
1212
import org.apache.lucene.document.SortedNumericDocValuesField;
1313
import org.apache.lucene.document.SortedSetDocValuesField;
14+
import org.apache.lucene.index.FilteredTermsEnum;
1415
import org.apache.lucene.index.IndexOptions;
1516
import org.apache.lucene.index.Term;
17+
import org.apache.lucene.index.Terms;
18+
import org.apache.lucene.index.TermsEnum;
1619
import org.apache.lucene.search.BooleanClause;
1720
import org.apache.lucene.search.BooleanClause.Occur;
1821
import org.apache.lucene.search.BooleanQuery;
1922
import org.apache.lucene.search.DocValuesFieldExistsQuery;
2023
import org.apache.lucene.search.MultiTermQuery;
2124
import org.apache.lucene.search.Query;
25+
import org.apache.lucene.search.RegexpQuery;
2226
import org.apache.lucene.search.TermRangeQuery;
27+
import org.apache.lucene.util.AttributeSource;
2328
import org.apache.lucene.util.BytesRef;
2429
import org.elasticsearch.ElasticsearchException;
2530
import org.elasticsearch.common.Nullable;
@@ -207,6 +212,46 @@ public Query prefixQuery(String value, MultiTermQuery.RewriteMethod method, Quer
207212
return wildcardQuery(value + "*", method, context);
208213
}
209214

215+
@Override
216+
public Query regexpQuery(
217+
String value,
218+
int flags,
219+
int maxDeterminizedStates,
220+
@Nullable MultiTermQuery.RewriteMethod method,
221+
QueryShardContext context
222+
) {
223+
if (context.allowExpensiveQueries() == false) {
224+
throw new ElasticsearchException(
225+
"[regexp] queries cannot be executed when '" + ALLOW_EXPENSIVE_QUERIES.getKey() + "' is set to false."
226+
);
227+
}
228+
failIfNotIndexed();
229+
RegexpQuery query = new RegexpQuery(new Term(name(), new BytesRef(value)), flags, maxDeterminizedStates) {
230+
231+
@Override
232+
protected TermsEnum getTermsEnum(Terms terms, AttributeSource atts) throws IOException {
233+
return new FilteredTermsEnum(terms.iterator(), false) {
234+
235+
@Override
236+
protected AcceptStatus accept(BytesRef term) throws IOException {
237+
byte[] decoded = VersionEncoder.decodeVersion(term).getBytes();
238+
boolean accepted = compiled.runAutomaton.run(decoded, 0, decoded.length);
239+
// System.out.println(accepted + " : " + VersionEncoder.decodeVersion(term));
240+
if (accepted) {
241+
return AcceptStatus.YES;
242+
}
243+
return AcceptStatus.NO;
244+
}
245+
};
246+
}
247+
};
248+
249+
if (method != null) {
250+
query.setRewriteMethod(method);
251+
}
252+
return query;
253+
}
254+
210255
@Override
211256
public Query wildcardQuery(String value, MultiTermQuery.RewriteMethod method, QueryShardContext context) {
212257
if (context.allowExpensiveQueries() == false) {

x-pack/plugin/versionfield/src/test/java/org/elasticsearch/xpack/versionfield/VersionStringFieldMapperTests.java

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,11 @@ public class VersionStringFieldMapperTests extends ESSingleNodeTestCase {
2828

2929
@Override
3030
protected Collection<Class<? extends Plugin>> getPlugins() {
31-
// return pluginList(VersionFieldPlugin.class, LocalStateCompositeXPackPlugin.class, PainlessPlugin.class);
32-
// TODO PainlessPlugin loading doesn't work when test is run through "gradle check"
3331
return pluginList(VersionFieldPlugin.class, LocalStateCompositeXPackPlugin.class);
3432
}
3533

3634
public String setUpIndex(String indexName) throws IOException {
37-
createIndex(
38-
indexName,
39-
Settings.builder().put("index.number_of_shards", 1).build(),
40-
"_doc",
41-
"version",
42-
"type=version",
43-
"foo",
44-
"type=keyword"
45-
);
35+
createIndex(indexName, Settings.builder().put("index.number_of_shards", 1).build(), "_doc", "version", "type=version");
4636
ensureGreen(indexName);
4737

4838
client().prepareIndex(indexName).setId("1").setSource(jsonBuilder().startObject().field("version", "11.1.0").endObject()).get();
@@ -186,6 +176,44 @@ public void testSort() throws IOException {
186176
assertEquals("21.11.0", hits[5].getSortValues()[0]);
187177
}
188178

179+
public void testRegexQuery() throws Exception {
180+
String indexName = "test_regex";
181+
createIndex(indexName, Settings.builder().put("index.number_of_shards", 1).build(), "_doc", "version", "type=version");
182+
ensureGreen(indexName);
183+
184+
client().prepareIndex(indexName)
185+
.setId("1")
186+
.setSource(jsonBuilder().startObject().field("version", "1.0.0-alpha.2.1.0-rc.1").endObject())
187+
.get();
188+
client().prepareIndex(indexName)
189+
.setId("2")
190+
.setSource(jsonBuilder().startObject().field("version", "1.3.0+build.1234567").endObject())
191+
.get();
192+
client().prepareIndex(indexName)
193+
.setId("3")
194+
.setSource(jsonBuilder().startObject().field("version", "2.1.0-alpha.beta").endObject())
195+
.get();
196+
client().prepareIndex(indexName).setId("4").setSource(jsonBuilder().startObject().field("version", "2.1.0").endObject()).get();
197+
client().prepareIndex(indexName).setId("5").setSource(jsonBuilder().startObject().field("version", "2.33.0").endObject()).get();
198+
client().admin().indices().prepareRefresh(indexName).get();
199+
200+
// regex
201+
SearchResponse response = client().prepareSearch(indexName).setQuery(QueryBuilders.regexpQuery("version", "2.*0")).get();
202+
assertEquals(2, response.getHits().getTotalHits().value);
203+
assertEquals("2.1.0", response.getHits().getHits()[0].getSourceAsMap().get("version"));
204+
assertEquals("2.33.0", response.getHits().getHits()[1].getSourceAsMap().get("version"));
205+
206+
response = client().prepareSearch(indexName).setQuery(QueryBuilders.regexpQuery("version", "<0-10>.<0-10>.*al.*")).get();
207+
assertEquals(2, response.getHits().getTotalHits().value);
208+
assertEquals("1.0.0-alpha.2.1.0-rc.1", response.getHits().getHits()[0].getSourceAsMap().get("version"));
209+
assertEquals("2.1.0-alpha.beta", response.getHits().getHits()[1].getSourceAsMap().get("version"));
210+
211+
response = client().prepareSearch(indexName).setQuery(QueryBuilders.regexpQuery("version", "1.[0-9].[0-9].*")).get();
212+
assertEquals(2, response.getHits().getTotalHits().value);
213+
assertEquals("1.0.0-alpha.2.1.0-rc.1", response.getHits().getHits()[0].getSourceAsMap().get("version"));
214+
assertEquals("1.3.0+build.1234567", response.getHits().getHits()[1].getSourceAsMap().get("version"));
215+
}
216+
189217
public void testWildcardQuery() throws Exception {
190218
String indexName = "test_wildcard";
191219
createIndex(

0 commit comments

Comments
 (0)