From fc9b63877e732b8e01fc33d4bb3e65ce24e01143 Mon Sep 17 00:00:00 2001 From: Jim Ferenczi Date: Wed, 30 Nov 2016 23:11:38 +0100 Subject: [PATCH] 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 --- .../elasticsearch/index/mapper/AllFieldMapper.java | 1 - .../elasticsearch/index/mapper/MappedFieldType.java | 7 +++++++ .../elasticsearch/index/mapper/TypeFieldMapper.java | 4 ++++ .../index/query/SpanTermQueryBuilderTests.java | 12 ++++++++++-- .../index/query/WildcardQueryBuilderTests.java | 11 +++++++++++ 5 files changed, 32 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/elasticsearch/index/mapper/AllFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/AllFieldMapper.java index a3db4b5f9f3..49b8fb085d6 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/AllFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/AllFieldMapper.java @@ -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; diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java index 5b80986b142..1c07420d262 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MappedFieldType.java @@ -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); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/TypeFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/TypeFieldMapper.java index 57ce082fca8..551208c797e 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/TypeFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/TypeFieldMapper.java @@ -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()); diff --git a/core/src/test/java/org/elasticsearch/index/query/SpanTermQueryBuilderTests.java b/core/src/test/java/org/elasticsearch/index/query/SpanTermQueryBuilderTests.java index 3ca2624205c..c3c81b7c25e 100644 --- a/core/src/test/java/org/elasticsearch/index/query/SpanTermQueryBuilderTests.java +++ b/core/src/test/java/org/elasticsearch/index/query/SpanTermQueryBuilderTests.java @@ -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 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); + } + } }