Remove MappedFieldType.useTermQueryWithQueryString() and isNumeric(). #17599

In both cases, what elasticsearch is really interested in is whether the field
is an analyzed string field. So it can just check `tokenized()` instead.
This commit is contained in:
Adrien Grand 2016-04-07 18:44:00 +02:00
parent 3460fdb3a4
commit a14db8e17e
14 changed files with 23 additions and 77 deletions

View File

@ -215,7 +215,8 @@ public class MapperQueryParser extends QueryParser {
} }
if (currentFieldType != null) { if (currentFieldType != null) {
Query query = null; Query query = null;
if (currentFieldType.useTermQueryWithQueryString()) { if (currentFieldType.tokenized() == false) {
// this might be a structured field like a numeric
try { try {
query = currentFieldType.termQuery(queryText, context); query = currentFieldType.termQuery(queryText, context);
} catch (RuntimeException e) { } catch (RuntimeException e) {
@ -326,7 +327,7 @@ public class MapperQueryParser extends QueryParser {
private Query getRangeQuerySingle(String field, String part1, String part2, boolean startInclusive, boolean endInclusive) { private Query getRangeQuerySingle(String field, String part1, String part2, boolean startInclusive, boolean endInclusive) {
currentFieldType = context.fieldMapper(field); currentFieldType = context.fieldMapper(field);
if (currentFieldType != null) { if (currentFieldType != null) {
if (lowercaseExpandedTerms && !currentFieldType.isNumeric()) { if (lowercaseExpandedTerms && currentFieldType.tokenized()) {
part1 = part1 == null ? null : part1.toLowerCase(locale); part1 = part1 == null ? null : part1.toLowerCase(locale);
part2 = part2 == null ? null : part2.toLowerCase(locale); part2 = part2 == null ? null : part2.toLowerCase(locale);
} }
@ -463,7 +464,7 @@ public class MapperQueryParser extends QueryParser {
setAnalyzer(context.getSearchAnalyzer(currentFieldType)); setAnalyzer(context.getSearchAnalyzer(currentFieldType));
} }
Query query = null; Query query = null;
if (currentFieldType.useTermQueryWithQueryString()) { if (currentFieldType.tokenized() == false) {
query = currentFieldType.prefixQuery(termStr, multiTermRewriteMethod, context); query = currentFieldType.prefixQuery(termStr, multiTermRewriteMethod, context);
} }
if (query == null) { if (query == null) {
@ -722,7 +723,7 @@ public class MapperQueryParser extends QueryParser {
setAnalyzer(context.getSearchAnalyzer(currentFieldType)); setAnalyzer(context.getSearchAnalyzer(currentFieldType));
} }
Query query = null; Query query = null;
if (currentFieldType.useTermQueryWithQueryString()) { if (currentFieldType.tokenized() == false) {
query = currentFieldType.regexpQuery(termStr, RegExp.ALL, maxDeterminizedStates, multiTermRewriteMethod, context); query = currentFieldType.regexpQuery(termStr, RegExp.ALL, maxDeterminizedStates, multiTermRewriteMethod, context);
} }
if (query == null) { if (query == null) {

View File

@ -128,8 +128,8 @@ public class TransportAnalyzeAction extends TransportSingleShardAction<AnalyzeRe
} }
MappedFieldType fieldType = indexService.mapperService().fullName(request.field()); MappedFieldType fieldType = indexService.mapperService().fullName(request.field());
if (fieldType != null) { if (fieldType != null) {
if (fieldType.isNumeric()) { if (fieldType.tokenized() == false) {
throw new IllegalArgumentException("Can't process field [" + request.field() + "], Analysis requests are not supported on numeric fields"); throw new IllegalArgumentException("Can't process field [" + request.field() + "], Analysis requests are only supported on tokenized fields");
} }
analyzer = fieldType.indexAnalyzer(); analyzer = fieldType.indexAnalyzer();
field = fieldType.name(); field = fieldType.name();

View File

@ -222,10 +222,6 @@ public abstract class MappedFieldType extends FieldType {
} }
} }
public boolean isNumeric() {
return false;
}
public boolean isSortable() { public boolean isSortable() {
return true; return true;
} }
@ -325,14 +321,6 @@ public abstract class MappedFieldType extends FieldType {
return BytesRefs.toBytesRef(value); return BytesRefs.toBytesRef(value);
} }
/**
* Should the field query {@link #termQuery(Object, org.elasticsearch.index.query.QueryShardContext)} be used when detecting this
* field in query string.
*/
public boolean useTermQueryWithQueryString() {
return false;
}
/** /**
* Creates a term associated with the field of this mapper for the given * Creates a term associated with the field of this mapper for the given
* value. Its important to use termQuery when building term queries because * value. Its important to use termQuery when building term queries because

View File

@ -191,11 +191,6 @@ public class BooleanFieldMapper extends FieldMapper {
return value(value); return value(value);
} }
@Override
public boolean useTermQueryWithQueryString() {
return true;
}
@Override @Override
public IndexFieldData.Builder fielddataBuilder() { public IndexFieldData.Builder fielddataBuilder() {
failIfNoDocValues(); failIfNoDocValues();

View File

@ -172,16 +172,6 @@ public abstract class NumberFieldMapper extends FieldMapper implements AllFieldM
@Override @Override
public abstract Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions); public abstract Query fuzzyQuery(Object value, Fuzziness fuzziness, int prefixLength, int maxExpansions, boolean transpositions);
@Override
public boolean useTermQueryWithQueryString() {
return true;
}
@Override
public boolean isNumeric() {
return true;
}
@Override @Override
public DocValueFormat docValueFormat(@Nullable String format, DateTimeZone timeZone) { public DocValueFormat docValueFormat(@Nullable String format, DateTimeZone timeZone) {
if (timeZone != null) { if (timeZone != null) {
@ -205,6 +195,7 @@ public abstract class NumberFieldMapper extends FieldMapper implements AllFieldM
Explicit<Boolean> ignoreMalformed, Explicit<Boolean> coerce, Settings indexSettings, Explicit<Boolean> ignoreMalformed, Explicit<Boolean> coerce, Settings indexSettings,
MultiFields multiFields, CopyTo copyTo) { MultiFields multiFields, CopyTo copyTo) {
super(simpleName, fieldType, defaultFieldType, indexSettings, multiFields, copyTo); super(simpleName, fieldType, defaultFieldType, indexSettings, multiFields, copyTo);
assert fieldType.tokenized() == false;
this.ignoreMalformed = ignoreMalformed; this.ignoreMalformed = ignoreMalformed;
this.coerce = coerce; this.coerce = coerce;
} }

View File

@ -188,11 +188,6 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper {
return value.toString(); return value.toString();
} }
@Override
public boolean useTermQueryWithQueryString() {
return true;
}
@Override @Override
public Query termQuery(Object value, QueryShardContext context) { public Query termQuery(Object value, QueryShardContext context) {
if (isEnabled() == false) { if (isEnabled() == false) {

View File

@ -66,6 +66,7 @@ public class IdFieldMapper extends MetadataFieldMapper {
public static final MappedFieldType FIELD_TYPE = new IdFieldType(); public static final MappedFieldType FIELD_TYPE = new IdFieldType();
static { static {
FIELD_TYPE.setTokenized(false);
FIELD_TYPE.setIndexOptions(IndexOptions.NONE); FIELD_TYPE.setIndexOptions(IndexOptions.NONE);
FIELD_TYPE.setStored(false); FIELD_TYPE.setStored(false);
FIELD_TYPE.setOmitNorms(true); FIELD_TYPE.setOmitNorms(true);
@ -135,11 +136,6 @@ public class IdFieldMapper extends MetadataFieldMapper {
return value.toString(); return value.toString();
} }
@Override
public boolean useTermQueryWithQueryString() {
return true;
}
@Override @Override
public Query termQuery(Object value, @Nullable QueryShardContext context) { public Query termQuery(Object value, @Nullable QueryShardContext context) {
if (indexOptions() != IndexOptions.NONE || context == null) { if (indexOptions() != IndexOptions.NONE || context == null) {

View File

@ -123,16 +123,6 @@ public class IndexFieldMapper extends MetadataFieldMapper {
return CONTENT_TYPE; return CONTENT_TYPE;
} }
@Override
public boolean useTermQueryWithQueryString() {
// As we spoof the presence of an indexed field we have to override
// the default of returning false which otherwise leads MatchQuery
// et al to run an analyzer over the query string and then try to
// hit the search index. We need them to use our termQuery(..)
// method which checks index names
return true;
}
/** /**
* This termQuery impl looks at the context to determine the index that * This termQuery impl looks at the context to determine the index that
* is being queried and then returns a MATCH_ALL_QUERY or MATCH_NO_QUERY * is being queried and then returns a MATCH_ALL_QUERY or MATCH_NO_QUERY

View File

@ -72,6 +72,7 @@ public class ParentFieldMapper extends MetadataFieldMapper {
public static final ParentFieldType FIELD_TYPE = new ParentFieldType(); public static final ParentFieldType FIELD_TYPE = new ParentFieldType();
static { static {
FIELD_TYPE.setTokenized(false);
FIELD_TYPE.setIndexOptions(IndexOptions.NONE); FIELD_TYPE.setIndexOptions(IndexOptions.NONE);
FIELD_TYPE.setHasDocValues(true); FIELD_TYPE.setHasDocValues(true);
FIELD_TYPE.setDocValuesType(DocValuesType.SORTED); FIELD_TYPE.setDocValuesType(DocValuesType.SORTED);
@ -185,14 +186,6 @@ public class ParentFieldMapper extends MetadataFieldMapper {
return CONTENT_TYPE; return CONTENT_TYPE;
} }
/**
* We don't need to analyzer the text, and we need to convert it to UID...
*/
@Override
public boolean useTermQueryWithQueryString() {
return true;
}
@Override @Override
public Query termQuery(Object value, @Nullable QueryShardContext context) { public Query termQuery(Object value, @Nullable QueryShardContext context) {
return termsQuery(Collections.singletonList(value), context); return termsQuery(Collections.singletonList(value), context);

View File

@ -126,11 +126,6 @@ public class TypeFieldMapper extends MetadataFieldMapper {
return value.toString(); return value.toString();
} }
@Override
public boolean useTermQueryWithQueryString() {
return true;
}
@Override @Override
public Query termQuery(Object value, @Nullable QueryShardContext context) { public Query termQuery(Object value, @Nullable QueryShardContext context) {
if (indexOptions() == IndexOptions.NONE) { if (indexOptions() == IndexOptions.NONE) {

View File

@ -244,7 +244,7 @@ public class MatchQuery {
* passing through QueryBuilder. * passing through QueryBuilder.
*/ */
boolean noForcedAnalyzer = this.analyzer == null; boolean noForcedAnalyzer = this.analyzer == null;
if (fieldType != null && fieldType.useTermQueryWithQueryString() && noForcedAnalyzer) { if (fieldType != null && fieldType.tokenized() == false && noForcedAnalyzer) {
return termQuery(fieldType, value); return termQuery(fieldType, value);
} }

View File

@ -28,6 +28,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested; import org.elasticsearch.index.fielddata.IndexFieldData.XFieldComparatorSource.Nested;
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryParseContext;
@ -271,17 +272,18 @@ public class FieldSortBuilder extends SortBuilder<FieldSortBuilder> {
localSortMode = MultiValueMode.fromString(sortMode.toString()); localSortMode = MultiValueMode.fromString(sortMode.toString());
} }
if (fieldType.isNumeric() == false && (sortMode == SortMode.SUM || sortMode == SortMode.AVG || sortMode == SortMode.MEDIAN)) {
throw new QueryShardException(context, "we only support AVG, MEDIAN and SUM on number based fields");
}
boolean reverse = (order == SortOrder.DESC); boolean reverse = (order == SortOrder.DESC);
if (localSortMode == null) { if (localSortMode == null) {
localSortMode = reverse ? MultiValueMode.MAX : MultiValueMode.MIN; localSortMode = reverse ? MultiValueMode.MAX : MultiValueMode.MIN;
} }
final Nested nested = resolveNested(context, nestedPath, nestedFilter); final Nested nested = resolveNested(context, nestedPath, nestedFilter);
IndexFieldData.XFieldComparatorSource fieldComparatorSource = context.getForField(fieldType) IndexFieldData<?> fieldData = context.getForField(fieldType);
if (fieldData instanceof IndexNumericFieldData == false
&& (sortMode == SortMode.SUM || sortMode == SortMode.AVG || sortMode == SortMode.MEDIAN)) {
throw new QueryShardException(context, "we only support AVG, MEDIAN and SUM on number based fields");
}
IndexFieldData.XFieldComparatorSource fieldComparatorSource = fieldData
.comparatorSource(missing, localSortMode, nested); .comparatorSource(missing, localSortMode, nested);
return new SortField(fieldType.name(), fieldComparatorSource, reverse); return new SortField(fieldType.name(), fieldComparatorSource, reverse);
} }

View File

@ -32,10 +32,10 @@ import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.fielddata.IndexFieldData; import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.core.DateFieldMapper; import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.index.mapper.core.NumberFieldMapper;
import org.elasticsearch.script.ClassPermission; import org.elasticsearch.script.ClassPermission;
import org.elasticsearch.script.CompiledScript; import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.ExecutableScript; import org.elasticsearch.script.ExecutableScript;
@ -193,12 +193,12 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
if (fieldType == null) { if (fieldType == null) {
throw new ScriptException("Field [" + fieldname + "] used in expression does not exist in mappings"); throw new ScriptException("Field [" + fieldname + "] used in expression does not exist in mappings");
} }
if (fieldType.isNumeric() == false) {
IndexFieldData<?> fieldData = lookup.doc().fieldDataService().getForField(fieldType);
if (fieldData instanceof IndexNumericFieldData == false) {
// TODO: more context (which expression?) // TODO: more context (which expression?)
throw new ScriptException("Field [" + fieldname + "] used in expression must be numeric"); throw new ScriptException("Field [" + fieldname + "] used in expression must be numeric");
} }
IndexFieldData<?> fieldData = lookup.doc().fieldDataService().getForField((NumberFieldMapper.NumberFieldType) fieldType);
if (methodname == null) { if (methodname == null) {
bindings.add(variable, new FieldDataValueSource(fieldData, MultiValueMode.MIN)); bindings.add(variable, new FieldDataValueSource(fieldData, MultiValueMode.MIN));
} else { } else {

View File

@ -319,7 +319,7 @@ public class MoreExpressionTests extends ESIntegTestCase {
public void testNonNumericField() { public void testNonNumericField() {
client().prepareIndex("test", "doc", "1").setSource("text", "this is not a number").setRefresh(true).get(); client().prepareIndex("test", "doc", "1").setSource("text", "this is not a number").setRefresh(true).get();
try { try {
buildRequest("doc['text']").get(); buildRequest("doc['text.keyword']").get();
fail("Expected text field to cause execution failure"); fail("Expected text field to cause execution failure");
} catch (SearchPhaseExecutionException e) { } catch (SearchPhaseExecutionException e) {
assertThat(e.toString() + "should have contained ScriptException", assertThat(e.toString() + "should have contained ScriptException",