Fix range queries on _type field for singe type indices ()

With the introduction of single types in 6.x, the `_type` field is no longer
indexed, which leads to certain queries that were working before throw errors
now. One such query is the `range` query, that, if performed on a single typer
index, currently throws an IAE since the field is not indexed.
This change adds special treatment for this case in the TypeFieldMapper,
comparing the range queries lower and upper bound to the one existing type and
either returns a MatchAllDocs or a MatchNoDocs query.

Relates to 
Closes 
This commit is contained in:
Christoph Büscher 2018-07-18 09:12:28 +02:00 committed by GitHub
parent 487cfc3b3f
commit 15f95a9f93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 0 deletions
server/src
main/java/org/elasticsearch/index/mapper
test/java/org/elasticsearch/search/query

@ -35,6 +35,8 @@ import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermInSetQuery;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -90,6 +92,8 @@ public class TypeFieldMapper extends MetadataFieldMapper {
static final class TypeFieldType extends StringFieldType {
private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(ESLoggerFactory.getLogger(TypeFieldType.class));
TypeFieldType() {
}
@ -154,6 +158,29 @@ public class TypeFieldMapper extends MetadataFieldMapper {
}
}
@Override
public Query rangeQuery(Object lowerTerm, Object upperTerm, boolean includeLower, boolean includeUpper, QueryShardContext context) {
DEPRECATION_LOGGER.deprecatedAndMaybeLog("range_single_type",
"Running [range] query on [_type] field for an index with a single type. As types are deprecated, this functionality will be removed in future releases.");
Query result = new MatchAllDocsQuery();
String type = context.getMapperService().documentMapper().type();
if (type != null) {
BytesRef typeBytes = new BytesRef(type);
if (lowerTerm != null) {
int comp = indexedValueForSearch(lowerTerm).compareTo(typeBytes);
if (comp > 0 || (comp == 0 && includeLower == false)) {
result = new MatchNoDocsQuery("[_type] was lexicographically smaller than lower bound of range");
}
}
if (upperTerm != null) {
int comp = indexedValueForSearch(upperTerm).compareTo(typeBytes);
if (comp < 0 || (comp == 0 && includeUpper == false)) {
result = new MatchNoDocsQuery("[_type] was lexicographically greater than upper bound of range");
}
}
}
return result;
}
}
/**

@ -1822,4 +1822,40 @@ public class SearchQueryIT extends ESIntegTestCase {
SearchResponse searchResponse = client().prepareSearch("test").setQuery(range).get();
assertHitCount(searchResponse, 1);
}
public void testRangeQueryTypeField_31476() throws Exception {
assertAcked(prepareCreate("test").addMapping("foo", "field", "type=keyword"));
client().prepareIndex("test", "foo", "1").setSource("field", "value").get();
refresh();
RangeQueryBuilder range = new RangeQueryBuilder("_type").from("ape").to("zebra");
SearchResponse searchResponse = client().prepareSearch("test").setQuery(range).get();
assertHitCount(searchResponse, 1);
range = new RangeQueryBuilder("_type").from("monkey").to("zebra");
searchResponse = client().prepareSearch("test").setQuery(range).get();
assertHitCount(searchResponse, 0);
range = new RangeQueryBuilder("_type").from("ape").to("donkey");
searchResponse = client().prepareSearch("test").setQuery(range).get();
assertHitCount(searchResponse, 0);
range = new RangeQueryBuilder("_type").from("ape").to("foo").includeUpper(false);
searchResponse = client().prepareSearch("test").setQuery(range).get();
assertHitCount(searchResponse, 0);
range = new RangeQueryBuilder("_type").from("ape").to("foo").includeUpper(true);
searchResponse = client().prepareSearch("test").setQuery(range).get();
assertHitCount(searchResponse, 1);
range = new RangeQueryBuilder("_type").from("foo").to("zebra").includeLower(false);
searchResponse = client().prepareSearch("test").setQuery(range).get();
assertHitCount(searchResponse, 0);
range = new RangeQueryBuilder("_type").from("foo").to("zebra").includeLower(true);
searchResponse = client().prepareSearch("test").setQuery(range).get();
assertHitCount(searchResponse, 1);
}
}