Handle specialized term queries in MappedFieldType.extractTerm(TermQuery) (#21889)

For some fields we have a specialized implementation of a TermQuery that is specific for the field.
When these kind of fields are used in a wildcard query or a span term query it fails with an exception because they don't recognize the specialized form.
The impacted fields are [_all] and [_type] and the impacted queries are [span_term] and [wilcard].
This change handles these forms and correctly extracts the term inside them for further use.

Fixes #21882
This commit is contained in:
Jim Ferenczi 2016-11-30 23:11:38 +01:00 committed by GitHub
parent 92f05e796e
commit fc9b63877e
5 changed files with 32 additions and 3 deletions

View File

@ -19,7 +19,6 @@
package org.elasticsearch.index.mapper;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;

View File

@ -35,6 +35,7 @@ import org.apache.lucene.search.BoostQuery;
import org.elasticsearch.action.fieldstats.FieldStats;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.joda.DateMathParser;
import org.elasticsearch.common.lucene.all.AllTermQuery;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.fielddata.IndexFieldData;
@ -463,6 +464,12 @@ public abstract class MappedFieldType extends FieldType {
while (termQuery instanceof BoostQuery) {
termQuery = ((BoostQuery) termQuery).getQuery();
}
if (termQuery instanceof AllTermQuery) {
return ((AllTermQuery) termQuery).getTerm();
} else if (termQuery instanceof TypeFieldMapper.TypesQuery) {
assert ((TypeFieldMapper.TypesQuery) termQuery).getTerms().length == 1;
return new Term(TypeFieldMapper.NAME, ((TypeFieldMapper.TypesQuery) termQuery).getTerms()[0]);
}
if (termQuery instanceof TermQuery == false) {
throw new IllegalArgumentException("Cannot extract a term from a query of type "
+ termQuery.getClass() + ": " + termQuery);

View File

@ -186,6 +186,10 @@ public class TypeFieldMapper extends MetadataFieldMapper {
this.types = types;
}
public BytesRef[] getTerms() {
return types;
}
@Override
public Query rewrite(IndexReader reader) throws IOException {
final int threshold = Math.min(BOOLEAN_REWRITE_TERM_COUNT_THRESHOLD, BooleanQuery.getMaxClauseCount());

View File

@ -19,6 +19,7 @@
package org.elasticsearch.index.query;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
@ -26,8 +27,6 @@ import org.apache.lucene.search.spans.SpanTermQuery;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.index.mapper.MappedFieldType;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import org.elasticsearch.search.internal.SearchContext;
import java.io.IOException;
@ -132,4 +131,13 @@ public class SpanTermQueryBuilderTests extends AbstractTermQueryTestCase<SpanTer
assertEquals("[span_term] query doesn't support multiple fields, found [message1] and [message2]", e.getMessage());
}
public void testWithMetaDataField() throws IOException {
QueryShardContext context = createShardContext();
for (String field : new String[]{"_type", "_all"}) {
SpanTermQueryBuilder spanTermQueryBuilder = new SpanTermQueryBuilder(field, "toto");
Query query = spanTermQueryBuilder.toQuery(context);
Query expected = new SpanTermQuery(new Term(field, "toto"));
assertEquals(expected, query);
}
}
}

View File

@ -19,6 +19,7 @@
package org.elasticsearch.index.query;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.WildcardQuery;
import org.elasticsearch.common.ParsingException;
@ -125,4 +126,14 @@ public class WildcardQueryBuilderTests extends AbstractQueryTestCase<WildcardQue
e = expectThrows(ParsingException.class, () -> parseQuery(shortJson));
assertEquals("[wildcard] query doesn't support multiple fields, found [user1] and [user2]", e.getMessage());
}
public void testWithMetaDataField() throws IOException {
QueryShardContext context = createShardContext();
for (String field : new String[]{"_type", "_all"}) {
WildcardQueryBuilder wildcardQueryBuilder = new WildcardQueryBuilder(field, "toto");
Query query = wildcardQueryBuilder.toQuery(context);
Query expected = new WildcardQuery(new Term(field, "toto"));
assertEquals(expected, query);
}
}
}