Skip to content

Commit

Permalink
Support 'string'-style queries on metadata fields when reasonable. (#…
Browse files Browse the repository at this point in the history
…34089)

* Make sure 'ignored' and 'routing' field types inherit from StringFieldType.
* Add tests for prefix and regexp queries.
* Support prefix and regexp queries on _index fields.
  • Loading branch information
jtibshirani committed Sep 28, 2018
1 parent 9454c6a commit 4cbb21f
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext c
}
}

public static final class IgnoredFieldType extends TermBasedFieldType {
public static final class IgnoredFieldType extends StringFieldType {

public IgnoredFieldType() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;


public class IndexFieldMapper extends MetadataFieldMapper {
Expand Down Expand Up @@ -155,14 +156,43 @@ public Query termsQuery(List values, QueryShardContext context) {
+ " vs. " + values);
}

@Override
public Query prefixQuery(String value,
@Nullable MultiTermQuery.RewriteMethod method,
QueryShardContext context) {
String indexName = context.getFullyQualifiedIndex().getName();
if (indexName.startsWith(value)) {
return Queries.newMatchAllQuery();
} else {
return Queries.newMatchNoDocsQuery("The index [" + indexName +
"] doesn't match the provided prefix [" + value + "].");
}
}

@Override
public Query regexpQuery(String value, int flags, int maxDeterminizedStates,
MultiTermQuery.RewriteMethod method, QueryShardContext context) {
String indexName = context.getFullyQualifiedIndex().getName();
Pattern pattern = Regex.compile(value, Regex.flagsToString(flags));

if (pattern.matcher(indexName).matches()) {
return Queries.newMatchAllQuery();
} else {
return Queries.newMatchNoDocsQuery("The index [" + indexName +
"] doesn't match the provided pattern [" + value + "].");
}
}

@Override
public Query wildcardQuery(String value,
@Nullable MultiTermQuery.RewriteMethod method,
QueryShardContext context) {
if (isSameIndex(value, context.getFullyQualifiedIndex().getName())) {
String indexName = context.getFullyQualifiedIndex().getName();
if (isSameIndex(value, indexName)) {
return Queries.newMatchAllQuery();
} else {
return Queries.newMatchNoDocsQuery("Index didn't match. Index queried: " + context.index().getName() + " vs. " + value);
return Queries.newMatchNoDocsQuery("The index [" + indexName +
"] doesn't match the provided pattern [" + value + "].");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public MetadataFieldMapper getDefault(MappedFieldType fieldType, ParserContext c
}
}

static final class RoutingFieldType extends TermBasedFieldType {
static final class RoutingFieldType extends StringFieldType {

RoutingFieldType() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,45 @@

package org.elasticsearch.index.mapper;

import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RegexpQuery;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.util.BytesRef;

public class IgnoredFieldTypeTests extends FieldTypeTestCase {

@Override
protected MappedFieldType createDefaultFieldType() {
return new IgnoredFieldMapper.IgnoredFieldType();
}

public void testPrefixQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);

Query expected = new PrefixQuery(new Term("field", new BytesRef("foo*")));
assertEquals(expected, ft.prefixQuery("foo*", null, null));
}

public void testRegexpQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);

Query expected = new RegexpQuery(new Term("field", new BytesRef("foo?")));
assertEquals(expected, ft.regexpQuery("foo?", 0, 10, null, null));
}

public void testWildcardQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);

Query expected = new WildcardQuery(new Term("field", new BytesRef("foo*")));
assertEquals(expected, ft.wildcardQuery("foo*", null, null));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,56 @@
*/
package org.elasticsearch.index.mapper;

import org.elasticsearch.index.mapper.IndexFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.query.QueryShardContext;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class IndexFieldTypeTests extends FieldTypeTestCase {

@Override
protected MappedFieldType createDefaultFieldType() {
return new IndexFieldMapper.IndexFieldType();
}

public void testPrefixQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);

assertEquals(new MatchAllDocsQuery(), ft.prefixQuery("ind", null, createContext()));
assertEquals(new MatchNoDocsQuery(), ft.prefixQuery("other_ind", null, createContext()));
}

public void testRegexpQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);

assertEquals(new MatchAllDocsQuery(), ft.regexpQuery("ind.x", 0, 10, null, createContext()));
assertEquals(new MatchNoDocsQuery(), ft.regexpQuery("ind?x", 0, 10, null, createContext()));
}

public void testWildcardQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);

assertEquals(new MatchAllDocsQuery(), ft.wildcardQuery("ind*x", null, createContext()));
assertEquals(new MatchNoDocsQuery(), ft.wildcardQuery("other_ind*x", null, createContext()));
}

private QueryShardContext createContext() {
QueryShardContext context = mock(QueryShardContext.class);

Index index = new Index("index", "123");
when(context.getFullyQualifiedIndex()).thenReturn(index);
when(context.index()).thenReturn(index);

return context;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,44 @@
*/
package org.elasticsearch.index.mapper;

import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.RoutingFieldMapper;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RegexpQuery;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.util.BytesRef;

public class RoutingFieldTypeTests extends FieldTypeTestCase {
@Override
protected MappedFieldType createDefaultFieldType() {
return new RoutingFieldMapper.RoutingFieldType();
}

public void testPrefixQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);

Query expected = new PrefixQuery(new Term("field", new BytesRef("foo*")));
assertEquals(expected, ft.prefixQuery("foo*", null, null));
}

public void testRegexpQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);

Query expected = new RegexpQuery(new Term("field", new BytesRef("foo?")));
assertEquals(expected, ft.regexpQuery("foo?", 0, 10, null, null));
}

public void testWildcardQuery() {
MappedFieldType ft = createDefaultFieldType();
ft.setName("field");
ft.setIndexOptions(IndexOptions.DOCS);

Query expected = new WildcardQuery(new Term("field", new BytesRef("foo*")));
assertEquals(expected, ft.wildcardQuery("foo*", null, null));
}
}

0 comments on commit 4cbb21f

Please sign in to comment.