Support 'string'-style queries on metadata fields when reasonable. (#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.
This commit is contained in:
parent
33a264a408
commit
9cd4f70a67
|
@ -85,7 +85,7 @@ public final class IgnoredFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class IgnoredFieldType extends TermBasedFieldType {
|
public static final class IgnoredFieldType extends StringFieldType {
|
||||||
|
|
||||||
public IgnoredFieldType() {
|
public IgnoredFieldType() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.elasticsearch.index.query.QueryShardContext;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
||||||
public class IndexFieldMapper extends MetadataFieldMapper {
|
public class IndexFieldMapper extends MetadataFieldMapper {
|
||||||
|
@ -151,14 +152,43 @@ public class IndexFieldMapper extends MetadataFieldMapper {
|
||||||
+ " vs. " + values);
|
+ " 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
|
@Override
|
||||||
public Query wildcardQuery(String value,
|
public Query wildcardQuery(String value,
|
||||||
@Nullable MultiTermQuery.RewriteMethod method,
|
@Nullable MultiTermQuery.RewriteMethod method,
|
||||||
QueryShardContext context) {
|
QueryShardContext context) {
|
||||||
if (isSameIndex(value, context.getFullyQualifiedIndex().getName())) {
|
String indexName = context.getFullyQualifiedIndex().getName();
|
||||||
|
if (isSameIndex(value, indexName)) {
|
||||||
return Queries.newMatchAllQuery();
|
return Queries.newMatchAllQuery();
|
||||||
} else {
|
} 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 + "].");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ public class RoutingFieldMapper extends MetadataFieldMapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final class RoutingFieldType extends TermBasedFieldType {
|
static final class RoutingFieldType extends StringFieldType {
|
||||||
|
|
||||||
RoutingFieldType() {
|
RoutingFieldType() {
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,14 @@
|
||||||
|
|
||||||
package org.elasticsearch.index.mapper;
|
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 {
|
public class IgnoredFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,4 +34,30 @@ public class IgnoredFieldTypeTests extends FieldTypeTestCase {
|
||||||
return new IgnoredFieldMapper.IgnoredFieldType();
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,56 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.elasticsearch.index.mapper.IndexFieldMapper;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
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 {
|
public class IndexFieldTypeTests extends FieldTypeTestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected MappedFieldType createDefaultFieldType() {
|
protected MappedFieldType createDefaultFieldType() {
|
||||||
return new IndexFieldMapper.IndexFieldType();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,44 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.index.mapper;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
import org.elasticsearch.index.mapper.MappedFieldType;
|
import org.apache.lucene.index.IndexOptions;
|
||||||
import org.elasticsearch.index.mapper.RoutingFieldMapper;
|
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 {
|
public class RoutingFieldTypeTests extends FieldTypeTestCase {
|
||||||
@Override
|
@Override
|
||||||
protected MappedFieldType createDefaultFieldType() {
|
protected MappedFieldType createDefaultFieldType() {
|
||||||
return new RoutingFieldMapper.RoutingFieldType();
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue