Add text search information to MappedFieldType (#58230) (#58432)

Now that MappedFieldType no longer extends lucene's FieldType, we need to have a
way of getting the index information about a field necessary for building text queries,
building term vectors, highlighting, etc. This commit introduces a new TextSearchInfo
abstraction that holds this information, and a getTextSearchInfo() method to
MappedFieldType to make it available. Field types that do not support text search can
just return null here.

This allows us to remove the MapperService.getLuceneFieldType() shim method.
This commit is contained in:
Alan Woodward 2020-06-23 14:37:26 +01:00 committed by GitHub
parent 519f41950a
commit 8ebd341710
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 344 additions and 238 deletions

View File

@ -98,7 +98,7 @@ public class RankFeatureFieldMapper extends FieldMapper {
private final boolean positiveScoreImpact; private final boolean positiveScoreImpact;
public RankFeatureFieldType(String name, Map<String, String> meta, boolean positiveScoreImpact) { public RankFeatureFieldType(String name, Map<String, String> meta, boolean positiveScoreImpact) {
super(name, true, false, meta); super(name, true, false, TextSearchInfo.NONE, meta);
this.positiveScoreImpact = positiveScoreImpact; this.positiveScoreImpact = positiveScoreImpact;
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);

View File

@ -89,7 +89,7 @@ public class RankFeatureMetaFieldMapper extends MetadataFieldMapper {
public static final RankFeatureMetaFieldType INSTANCE = new RankFeatureMetaFieldType(); public static final RankFeatureMetaFieldType INSTANCE = new RankFeatureMetaFieldType();
private RankFeatureMetaFieldType() { private RankFeatureMetaFieldType() {
super(NAME, false, false, Collections.emptyMap()); super(NAME, false, false, TextSearchInfo.NONE, Collections.emptyMap());
} }
protected RankFeatureMetaFieldType(RankFeatureMetaFieldType ref) { protected RankFeatureMetaFieldType(RankFeatureMetaFieldType ref) {

View File

@ -76,7 +76,7 @@ public class RankFeaturesFieldMapper extends FieldMapper {
public static final class RankFeaturesFieldType extends MappedFieldType { public static final class RankFeaturesFieldType extends MappedFieldType {
public RankFeaturesFieldType(String name, Map<String, String> meta) { public RankFeaturesFieldType(String name, Map<String, String> meta) {
super(name, false, false, meta); super(name, false, false, TextSearchInfo.NONE, meta);
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
} }

View File

@ -185,7 +185,7 @@ public class ScaledFloatFieldMapper extends FieldMapper {
private final double scalingFactor; private final double scalingFactor;
public ScaledFloatFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta, double scalingFactor) { public ScaledFloatFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta, double scalingFactor) {
super(name, indexed, hasDocValues, meta); super(name, indexed, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
this.scalingFactor = scalingFactor; this.scalingFactor = scalingFactor;
} }

View File

@ -157,16 +157,19 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
@Override @Override
public SearchAsYouTypeFieldMapper build(Mapper.BuilderContext context) { public SearchAsYouTypeFieldMapper build(Mapper.BuilderContext context) {
boolean hasNorms = fieldType.omitNorms() == false; SearchAsYouTypeFieldType ft = new SearchAsYouTypeFieldType(buildFullName(context), fieldType, meta);
SearchAsYouTypeFieldType ft = new SearchAsYouTypeFieldType(buildFullName(context), indexed, meta, hasNorms);
ft.setIndexAnalyzer(indexAnalyzer); ft.setIndexAnalyzer(indexAnalyzer);
ft.setSearchAnalyzer(searchAnalyzer); ft.setSearchAnalyzer(searchAnalyzer);
ft.setSearchQuoteAnalyzer(searchQuoteAnalyzer); ft.setSearchQuoteAnalyzer(searchQuoteAnalyzer);
ft.setSimilarity(similarity); ft.setSimilarity(similarity);
// set up the prefix field // set up the prefix field
FieldType prefixft = new FieldType(fieldType);
prefixft.setStoreTermVectors(false);
prefixft.setOmitNorms(true);
prefixft.setStored(false);
final String fullName = buildFullName(context); final String fullName = buildFullName(context);
final PrefixFieldType prefixFieldType = new PrefixFieldType(fullName, Defaults.MIN_GRAM, Defaults.MAX_GRAM); final PrefixFieldType prefixFieldType = new PrefixFieldType(fullName, prefixft, Defaults.MIN_GRAM, Defaults.MAX_GRAM);
// wrap the root field's index analyzer with shingles and edge ngrams // wrap the root field's index analyzer with shingles and edge ngrams
final SearchAsYouTypeAnalyzer prefixIndexWrapper = final SearchAsYouTypeAnalyzer prefixIndexWrapper =
SearchAsYouTypeAnalyzer.withShingleAndPrefix(indexAnalyzer.analyzer(), maxShingleSize); SearchAsYouTypeAnalyzer.withShingleAndPrefix(indexAnalyzer.analyzer(), maxShingleSize);
@ -176,10 +179,6 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
// don't wrap the root field's search quote analyzer as prefix field doesn't support phrase queries // don't wrap the root field's search quote analyzer as prefix field doesn't support phrase queries
prefixFieldType.setIndexAnalyzer(new NamedAnalyzer(indexAnalyzer.name(), AnalyzerScope.INDEX, prefixIndexWrapper)); prefixFieldType.setIndexAnalyzer(new NamedAnalyzer(indexAnalyzer.name(), AnalyzerScope.INDEX, prefixIndexWrapper));
prefixFieldType.setSearchAnalyzer(new NamedAnalyzer(searchAnalyzer.name(), AnalyzerScope.INDEX, prefixSearchWrapper)); prefixFieldType.setSearchAnalyzer(new NamedAnalyzer(searchAnalyzer.name(), AnalyzerScope.INDEX, prefixSearchWrapper));
FieldType prefixft = new FieldType(fieldType);
prefixft.setStoreTermVectors(false);
prefixft.setOmitNorms(true);
prefixft.setStored(false);
final PrefixFieldMapper prefixFieldMapper = new PrefixFieldMapper(prefixft, prefixFieldType); final PrefixFieldMapper prefixFieldMapper = new PrefixFieldMapper(prefixft, prefixFieldType);
// set up the shingle fields // set up the shingle fields
@ -187,8 +186,10 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
final ShingleFieldType[] shingleFieldTypes = new ShingleFieldType[maxShingleSize - 1]; final ShingleFieldType[] shingleFieldTypes = new ShingleFieldType[maxShingleSize - 1];
for (int i = 0; i < shingleFieldMappers.length; i++) { for (int i = 0; i < shingleFieldMappers.length; i++) {
final int shingleSize = i + 2; final int shingleSize = i + 2;
FieldType shingleft = new FieldType(fieldType);
shingleft.setStored(false);
String fieldName = getShingleFieldName(buildFullName(context), shingleSize); String fieldName = getShingleFieldName(buildFullName(context), shingleSize);
final ShingleFieldType shingleFieldType = new ShingleFieldType(fieldName, shingleSize, hasNorms); final ShingleFieldType shingleFieldType = new ShingleFieldType(fieldName, shingleSize, shingleft);
// wrap the root field's index, search, and search quote analyzers with shingles // wrap the root field's index, search, and search quote analyzers with shingles
final SearchAsYouTypeAnalyzer shingleIndexWrapper = final SearchAsYouTypeAnalyzer shingleIndexWrapper =
SearchAsYouTypeAnalyzer.withShingle(indexAnalyzer.analyzer(), shingleSize); SearchAsYouTypeAnalyzer.withShingle(indexAnalyzer.analyzer(), shingleSize);
@ -202,8 +203,6 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
new NamedAnalyzer(searchQuoteAnalyzer.name(), AnalyzerScope.INDEX, shingleSearchQuoteWrapper)); new NamedAnalyzer(searchQuoteAnalyzer.name(), AnalyzerScope.INDEX, shingleSearchQuoteWrapper));
shingleFieldType.setPrefixFieldType(prefixFieldType); shingleFieldType.setPrefixFieldType(prefixFieldType);
shingleFieldTypes[i] = shingleFieldType; shingleFieldTypes[i] = shingleFieldType;
FieldType shingleft = new FieldType(fieldType);
shingleft.setStored(false);
shingleFieldMappers[i] = new ShingleFieldMapper(shingleft, shingleFieldType); shingleFieldMappers[i] = new ShingleFieldMapper(shingleft, shingleFieldType);
} }
ft.setPrefixField(prefixFieldType); ft.setPrefixField(prefixFieldType);
@ -235,12 +234,9 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
PrefixFieldType prefixField; PrefixFieldType prefixField;
ShingleFieldType[] shingleFields = new ShingleFieldType[0]; ShingleFieldType[] shingleFields = new ShingleFieldType[0];
final boolean hasNorms;
SearchAsYouTypeFieldType(String name, boolean indexed, Map<String, String> meta, boolean hasNorms) { SearchAsYouTypeFieldType(String name, FieldType fieldType, Map<String, String> meta) {
super(name, indexed, false, meta); super(name, fieldType.indexOptions() != IndexOptions.NONE, false, new TextSearchInfo(fieldType), meta);
this.hasNorms = hasNorms;
this.hasPositions = true;
} }
SearchAsYouTypeFieldType(SearchAsYouTypeFieldType other) { SearchAsYouTypeFieldType(SearchAsYouTypeFieldType other) {
@ -257,7 +253,6 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
} }
} }
} }
this.hasNorms = other.hasNorms;
} }
public void setPrefixField(PrefixFieldType prefixField) { public void setPrefixField(PrefixFieldType prefixField) {
@ -285,7 +280,7 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
@Override @Override
public Query existsQuery(QueryShardContext context) { public Query existsQuery(QueryShardContext context) {
if (hasNorms == false) { if (getTextSearchInfo().hasNorms() == false) {
return new TermQuery(new Term(FieldNamesFieldMapper.NAME, name())); return new TermQuery(new Term(FieldNamesFieldMapper.NAME, name()));
} else { } else {
return new NormsFieldExistsQuery(name()); return new NormsFieldExistsQuery(name());
@ -386,12 +381,11 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
final int maxChars; final int maxChars;
final String parentField; final String parentField;
PrefixFieldType(String parentField, int minChars, int maxChars) { PrefixFieldType(String parentField, FieldType fieldType, int minChars, int maxChars) {
super(parentField + PREFIX_FIELD_SUFFIX, true, false, Collections.emptyMap()); super(parentField + PREFIX_FIELD_SUFFIX, true, false, new TextSearchInfo(fieldType), Collections.emptyMap());
this.minChars = minChars; this.minChars = minChars;
this.maxChars = maxChars; this.maxChars = maxChars;
this.parentField = parentField; this.parentField = parentField;
this.hasPositions = true;
} }
PrefixFieldType(PrefixFieldType other) { PrefixFieldType(PrefixFieldType other) {
@ -399,7 +393,6 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
this.minChars = other.minChars; this.minChars = other.minChars;
this.maxChars = other.maxChars; this.maxChars = other.maxChars;
this.parentField = other.parentField; this.parentField = other.parentField;
this.hasPositions = other.hasPositions;
} }
boolean termLengthWithinBounds(int length) { boolean termLengthWithinBounds(int length) {
@ -539,21 +532,16 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
*/ */
static class ShingleFieldType extends StringFieldType { static class ShingleFieldType extends StringFieldType {
final int shingleSize; final int shingleSize;
final boolean hasNorms;
PrefixFieldType prefixFieldType; PrefixFieldType prefixFieldType;
ShingleFieldType(String name, int shingleSize, boolean hasNorms) { ShingleFieldType(String name, int shingleSize, FieldType fieldType) {
super(name, true, false, Collections.emptyMap()); super(name, true, false, new TextSearchInfo(fieldType), Collections.emptyMap());
this.shingleSize = shingleSize; this.shingleSize = shingleSize;
this.hasNorms = hasNorms;
this.hasPositions = true;
} }
ShingleFieldType(ShingleFieldType other) { ShingleFieldType(ShingleFieldType other) {
super(other); super(other);
this.shingleSize = other.shingleSize; this.shingleSize = other.shingleSize;
this.hasNorms = other.hasNorms;
this.hasPositions = other.hasPositions;
if (other.prefixFieldType != null) { if (other.prefixFieldType != null) {
this.prefixFieldType = other.prefixFieldType.clone(); this.prefixFieldType = other.prefixFieldType.clone();
} }
@ -575,7 +563,7 @@ public class SearchAsYouTypeFieldMapper extends FieldMapper {
@Override @Override
public Query existsQuery(QueryShardContext context) { public Query existsQuery(QueryShardContext context) {
if (hasNorms == false) { if (getTextSearchInfo().hasNorms() == false) {
return new TermQuery(new Term(FieldNamesFieldMapper.NAME, name())); return new TermQuery(new Term(FieldNamesFieldMapper.NAME, name()));
} else { } else {
return new NormsFieldExistsQuery(name()); return new NormsFieldExistsQuery(name());

View File

@ -19,6 +19,8 @@
package org.elasticsearch.index.mapper; package org.elasticsearch.index.mapper;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.search.ConstantScoreQuery; import org.apache.lucene.search.ConstantScoreQuery;
import org.apache.lucene.search.PrefixQuery; import org.apache.lucene.search.PrefixQuery;
@ -41,12 +43,17 @@ import static org.hamcrest.Matchers.equalTo;
public class SearchAsYouTypeFieldTypeTests extends FieldTypeTestCase<MappedFieldType> { public class SearchAsYouTypeFieldTypeTests extends FieldTypeTestCase<MappedFieldType> {
private static final String NAME = "a_field"; private static final String NAME = "a_field";
private static final FieldType UNSEARCHABLE = new FieldType();
static {
UNSEARCHABLE.setIndexOptions(IndexOptions.NONE);
UNSEARCHABLE.freeze();
}
@Override @Override
protected SearchAsYouTypeFieldType createDefaultFieldType(String name, Map<String, String> meta) { protected SearchAsYouTypeFieldType createDefaultFieldType(String name, Map<String, String> meta) {
final SearchAsYouTypeFieldType fieldType = new SearchAsYouTypeFieldType(name, true, meta, true); final SearchAsYouTypeFieldType fieldType = new SearchAsYouTypeFieldType(name, Defaults.FIELD_TYPE, meta);
fieldType.setPrefixField(new PrefixFieldType(NAME, Defaults.MIN_GRAM, Defaults.MAX_GRAM)); fieldType.setPrefixField(new PrefixFieldType(NAME, Defaults.FIELD_TYPE, Defaults.MIN_GRAM, Defaults.MAX_GRAM));
fieldType.setShingleFields(new ShingleFieldType[] { new ShingleFieldType(fieldType.name(), 2, true) }); fieldType.setShingleFields(new ShingleFieldType[] { new ShingleFieldType(fieldType.name(), 2, Defaults.FIELD_TYPE) });
return fieldType; return fieldType;
} }
@ -55,7 +62,7 @@ public class SearchAsYouTypeFieldTypeTests extends FieldTypeTestCase<MappedField
assertThat(fieldType.termQuery("foo", null), equalTo(new TermQuery(new Term(NAME, "foo")))); assertThat(fieldType.termQuery("foo", null), equalTo(new TermQuery(new Term(NAME, "foo"))));
SearchAsYouTypeFieldType unsearchable = new SearchAsYouTypeFieldType(NAME, false, Collections.emptyMap(), true); SearchAsYouTypeFieldType unsearchable = new SearchAsYouTypeFieldType(NAME, UNSEARCHABLE, Collections.emptyMap());
final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> unsearchable.termQuery("foo", null)); final IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> unsearchable.termQuery("foo", null));
assertThat(e.getMessage(), equalTo("Cannot search on field [" + NAME + "] since it is not indexed.")); assertThat(e.getMessage(), equalTo("Cannot search on field [" + NAME + "] since it is not indexed."));
} }
@ -66,7 +73,7 @@ public class SearchAsYouTypeFieldTypeTests extends FieldTypeTestCase<MappedField
assertThat(fieldType.termsQuery(asList("foo", "bar"), null), assertThat(fieldType.termsQuery(asList("foo", "bar"), null),
equalTo(new TermInSetQuery(NAME, asList(new BytesRef("foo"), new BytesRef("bar"))))); equalTo(new TermInSetQuery(NAME, asList(new BytesRef("foo"), new BytesRef("bar")))));
SearchAsYouTypeFieldType unsearchable = new SearchAsYouTypeFieldType(NAME, false, Collections.emptyMap(), true); SearchAsYouTypeFieldType unsearchable = new SearchAsYouTypeFieldType(NAME, UNSEARCHABLE, Collections.emptyMap());
final IllegalArgumentException e = final IllegalArgumentException e =
expectThrows(IllegalArgumentException.class, () -> unsearchable.termsQuery(asList("foo", "bar"), null)); expectThrows(IllegalArgumentException.class, () -> unsearchable.termsQuery(asList("foo", "bar"), null));
assertThat(e.getMessage(), equalTo("Cannot search on field [" + NAME + "] since it is not indexed.")); assertThat(e.getMessage(), equalTo("Cannot search on field [" + NAME + "] since it is not indexed."));

View File

@ -28,6 +28,7 @@ import org.elasticsearch.index.fielddata.plain.SortedSetOrdinalsIndexFieldData;
import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.StringFieldType; import org.elasticsearch.index.mapper.StringFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
@ -77,7 +78,7 @@ public class MetaJoinFieldMapper extends FieldMapper {
private final String joinField; private final String joinField;
MetaJoinFieldType(String joinField) { MetaJoinFieldType(String joinField) {
super(NAME, false, false, Collections.emptyMap()); super(NAME, false, false, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
this.joinField = joinField; this.joinField = joinField;
} }

View File

@ -38,6 +38,7 @@ import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.StringFieldType; import org.elasticsearch.index.mapper.StringFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
@ -94,7 +95,7 @@ public final class ParentIdFieldMapper extends FieldMapper {
public static final class ParentIdFieldType extends StringFieldType { public static final class ParentIdFieldType extends StringFieldType {
ParentIdFieldType(String name, boolean eagerGlobalOrdinals, Map<String, String> meta) { ParentIdFieldType(String name, boolean eagerGlobalOrdinals, Map<String, String> meta) {
super(name, true, true, meta); super(name, true, true, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
setEagerGlobalOrdinals(eagerGlobalOrdinals); setEagerGlobalOrdinals(eagerGlobalOrdinals);

View File

@ -43,6 +43,7 @@ import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.StringFieldType; import org.elasticsearch.index.mapper.StringFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
@ -205,7 +206,7 @@ public final class ParentJoinFieldMapper extends FieldMapper {
public static final class JoinFieldType extends StringFieldType { public static final class JoinFieldType extends StringFieldType {
public JoinFieldType(String name, Map<String, String> meta) { public JoinFieldType(String name, Map<String, String> meta) {
super(name, true, true, meta); super(name, true, true, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
} }

View File

@ -69,6 +69,7 @@ import org.elasticsearch.index.mapper.NumberFieldMapper;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.RangeFieldMapper; import org.elasticsearch.index.mapper.RangeFieldMapper;
import org.elasticsearch.index.mapper.RangeType; import org.elasticsearch.index.mapper.RangeType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.BoostingQueryBuilder; import org.elasticsearch.index.query.BoostingQueryBuilder;
import org.elasticsearch.index.query.ConstantScoreQueryBuilder; import org.elasticsearch.index.query.ConstantScoreQueryBuilder;
@ -202,7 +203,7 @@ public class PercolatorFieldMapper extends FieldMapper {
boolean mapUnmappedFieldsAsText; boolean mapUnmappedFieldsAsText;
PercolatorFieldType(String name, Map<String, String> meta) { PercolatorFieldType(String name, Map<String, String> meta) {
super(name, false, false, meta); super(name, false, false, TextSearchInfo.NONE, meta);
} }
PercolatorFieldType(PercolatorFieldType ref) { PercolatorFieldType(PercolatorFieldType ref) {

View File

@ -77,7 +77,7 @@ public class ICUCollationKeywordFieldMapper extends FieldMapper {
private final Collator collator; private final Collator collator;
public CollationFieldType(String name, boolean isSearchable, boolean hasDocValues, Collator collator, Map<String, String> meta) { public CollationFieldType(String name, boolean isSearchable, boolean hasDocValues, Collator collator, Map<String, String> meta) {
super(name, isSearchable, hasDocValues, meta); super(name, isSearchable, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
this.collator = collator; this.collator = collator;

View File

@ -124,7 +124,7 @@ public class AnnotatedTextFieldMapper extends FieldMapper {
} else { } else {
//Using the analyzer's default BUT need to do the same thing AnalysisRegistry.processAnalyzerFactory //Using the analyzer's default BUT need to do the same thing AnalysisRegistry.processAnalyzerFactory
// does to splice in new default of posIncGap=100 by wrapping the analyzer // does to splice in new default of posIncGap=100 by wrapping the analyzer
if (fieldType.indexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0) { if (hasPositions) {
int overrideInc = TextFieldMapper.Defaults.POSITION_INCREMENT_GAP; int overrideInc = TextFieldMapper.Defaults.POSITION_INCREMENT_GAP;
ft.setIndexAnalyzer(indexAnalyzer, overrideInc); ft.setIndexAnalyzer(indexAnalyzer, overrideInc);
ft.setSearchAnalyzer(new NamedAnalyzer(searchAnalyzer, overrideInc)); ft.setSearchAnalyzer(new NamedAnalyzer(searchAnalyzer, overrideInc));
@ -522,7 +522,7 @@ public class AnnotatedTextFieldMapper extends FieldMapper {
public static final class AnnotatedTextFieldType extends TextFieldMapper.TextFieldType { public static final class AnnotatedTextFieldType extends TextFieldMapper.TextFieldType {
public AnnotatedTextFieldType(String name, boolean hasPositions, Map<String, String> meta) { public AnnotatedTextFieldType(String name, boolean hasPositions, Map<String, String> meta) {
super(name, true, hasPositions, meta); super(name, hasPositions, meta);
} }
protected AnnotatedTextFieldType(AnnotatedTextFieldType ref) { protected AnnotatedTextFieldType(AnnotatedTextFieldType ref) {

View File

@ -35,6 +35,7 @@ import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.mapper.TypeParsers; import org.elasticsearch.index.mapper.TypeParsers;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.QueryShardException; import org.elasticsearch.index.query.QueryShardException;
@ -92,7 +93,7 @@ public class Murmur3FieldMapper extends FieldMapper {
// this only exists so a check can be done to match the field type to using murmur3 hashing... // this only exists so a check can be done to match the field type to using murmur3 hashing...
public static class Murmur3FieldType extends MappedFieldType { public static class Murmur3FieldType extends MappedFieldType {
public Murmur3FieldType(String name, Map<String, String> meta) { public Murmur3FieldType(String name, Map<String, String> meta) {
super(name, false, true, meta); super(name, false, true, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
} }
protected Murmur3FieldType(Murmur3FieldType ref) { protected Murmur3FieldType(Murmur3FieldType ref) {

View File

@ -175,7 +175,6 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
} }
@Override @Override
@SuppressWarnings("rawtypes")
public T parse(String name, Map<String, Object> node, ParserContext parserContext) public T parse(String name, Map<String, Object> node, ParserContext parserContext)
throws MapperParsingException { throws MapperParsingException {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
@ -189,7 +188,7 @@ public abstract class AbstractGeometryFieldMapper<Parsed, Processed> extends Fie
protected QueryProcessor geometryQueryBuilder; protected QueryProcessor geometryQueryBuilder;
protected AbstractGeometryFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta) { protected AbstractGeometryFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta) {
super(name, indexed, hasDocValues, meta); super(name, indexed, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
} }
protected AbstractGeometryFieldType(AbstractGeometryFieldType ref) { protected AbstractGeometryFieldType(AbstractGeometryFieldType ref) {

View File

@ -99,7 +99,7 @@ public class AllFieldMapper extends MetadataFieldMapper {
static final class AllFieldType extends StringFieldType { static final class AllFieldType extends StringFieldType {
AllFieldType() { AllFieldType() {
super(NAME, false, false, Collections.emptyMap()); super(NAME, false, false, TextSearchInfo.NONE, Collections.emptyMap());
} }
protected AllFieldType(AllFieldType ref) { protected AllFieldType(AllFieldType ref) {

View File

@ -99,7 +99,7 @@ public class BinaryFieldMapper extends FieldMapper {
public static final class BinaryFieldType extends MappedFieldType { public static final class BinaryFieldType extends MappedFieldType {
public BinaryFieldType(String name, boolean hasDocValues, Map<String, String> meta) { public BinaryFieldType(String name, boolean hasDocValues, Map<String, String> meta) {
super(name, false, hasDocValues, meta); super(name, false, hasDocValues, TextSearchInfo.NONE, meta);
} }
public BinaryFieldType(String name) { public BinaryFieldType(String name) {

View File

@ -118,7 +118,7 @@ public class BooleanFieldMapper extends FieldMapper {
public static final class BooleanFieldType extends TermBasedFieldType { public static final class BooleanFieldType extends TermBasedFieldType {
public BooleanFieldType(String name, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) { public BooleanFieldType(String name, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) {
super(name, isSearchable, hasDocValues, meta); super(name, isSearchable, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
} }
public BooleanFieldType(String name) { public BooleanFieldType(String name) {

View File

@ -194,12 +194,12 @@ public class CompletionFieldMapper extends FieldMapper {
private boolean preservePositionIncrements = Defaults.DEFAULT_POSITION_INCREMENTS; private boolean preservePositionIncrements = Defaults.DEFAULT_POSITION_INCREMENTS;
private ContextMappings contextMappings = null; private ContextMappings contextMappings = null;
public CompletionFieldType(String name, Map<String, String> meta) { public CompletionFieldType(String name, FieldType luceneFieldType, Map<String, String> meta) {
super(name, true, false, meta); super(name, true, false, new TextSearchInfo(luceneFieldType), meta);
} }
public CompletionFieldType(String name) { public CompletionFieldType(String name) {
this(name, Collections.emptyMap()); this(name, Defaults.FIELD_TYPE, Collections.emptyMap());
} }
private CompletionFieldType(CompletionFieldType ref) { private CompletionFieldType(CompletionFieldType ref) {
@ -395,7 +395,7 @@ public class CompletionFieldMapper extends FieldMapper {
@Override @Override
public CompletionFieldMapper build(BuilderContext context) { public CompletionFieldMapper build(BuilderContext context) {
checkCompletionContextsLimit(context); checkCompletionContextsLimit(context);
CompletionFieldType ft = new CompletionFieldType(buildFullName(context), meta); CompletionFieldType ft = new CompletionFieldType(buildFullName(context), this.fieldType, meta);
ft.setContextMappings(contextMappings); ft.setContextMappings(contextMappings);
ft.setPreservePositionIncrements(preservePositionIncrements); ft.setPreservePositionIncrements(preservePositionIncrements);
ft.setPreserveSep(preserveSeparators); ft.setPreserveSep(preserveSeparators);

View File

@ -42,7 +42,7 @@ import java.util.Map;
public abstract class ConstantFieldType extends MappedFieldType { public abstract class ConstantFieldType extends MappedFieldType {
public ConstantFieldType(String name, Map<String, String> meta) { public ConstantFieldType(String name, Map<String, String> meta) {
super(name, true, true, meta); super(name, true, true, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
} }
public ConstantFieldType(ConstantFieldType other) { public ConstantFieldType(ConstantFieldType other) {

View File

@ -308,7 +308,7 @@ public final class DateFieldMapper extends FieldMapper {
public DateFieldType(String name, boolean isSearchable, boolean hasDocValues, public DateFieldType(String name, boolean isSearchable, boolean hasDocValues,
DateFormatter dateTimeFormatter, Resolution resolution, Map<String, String> meta) { DateFormatter dateTimeFormatter, Resolution resolution, Map<String, String> meta) {
super(name, isSearchable, hasDocValues, meta); super(name, isSearchable, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
this.dateTimeFormatter = dateTimeFormatter; this.dateTimeFormatter = dateTimeFormatter;
this.dateMathParser = dateTimeFormatter.toDateMathParser(); this.dateMathParser = dateTimeFormatter.toDateMathParser();
this.resolution = resolution; this.resolution = resolution;

View File

@ -132,7 +132,7 @@ public class FieldNamesFieldMapper extends MetadataFieldMapper {
private boolean enabled = Defaults.ENABLED; private boolean enabled = Defaults.ENABLED;
public FieldNamesFieldType() { public FieldNamesFieldType() {
super(Defaults.NAME, true, false, Collections.emptyMap()); super(Defaults.NAME, true, false, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
} }
protected FieldNamesFieldType(FieldNamesFieldType ref) { protected FieldNamesFieldType(FieldNamesFieldType ref) {

View File

@ -117,7 +117,7 @@ public class IdFieldMapper extends MetadataFieldMapper {
public static final IdFieldType INSTANCE = new IdFieldType(); public static final IdFieldType INSTANCE = new IdFieldType();
private IdFieldType() { private IdFieldType() {
super(NAME, true, false, Collections.emptyMap()); super(NAME, true, false, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
} }

View File

@ -84,7 +84,7 @@ public final class IgnoredFieldMapper extends MetadataFieldMapper {
public static final IgnoredFieldType INSTANCE = new IgnoredFieldType(); public static final IgnoredFieldType INSTANCE = new IgnoredFieldType();
private IgnoredFieldType() { private IgnoredFieldType() {
super(NAME, true, false, Collections.emptyMap()); super(NAME, true, false, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
} }
protected IgnoredFieldType(IgnoredFieldType ref) { protected IgnoredFieldType(IgnoredFieldType ref) {

View File

@ -141,7 +141,7 @@ public class IpFieldMapper extends FieldMapper {
public static final class IpFieldType extends SimpleMappedFieldType { public static final class IpFieldType extends SimpleMappedFieldType {
public IpFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta) { public IpFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta) {
super(name, indexed, hasDocValues, meta); super(name, indexed, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
} }
public IpFieldType(String name) { public IpFieldType(String name) {

View File

@ -165,7 +165,7 @@ public final class KeywordFieldMapper extends FieldMapper {
// TODO should this be a Lucene global analyzer as well? // TODO should this be a Lucene global analyzer as well?
searchAnalyzer = new NamedAnalyzer("whitespace", AnalyzerScope.INDEX, new WhitespaceAnalyzer()); searchAnalyzer = new NamedAnalyzer("whitespace", AnalyzerScope.INDEX, new WhitespaceAnalyzer());
} }
return new KeywordFieldType(buildFullName(context), indexed, hasDocValues, fieldType.omitNorms() == false, return new KeywordFieldType(buildFullName(context), hasDocValues, fieldType,
eagerGlobalOrdinals, normalizer, searchAnalyzer, similarity, meta, boost); eagerGlobalOrdinals, normalizer, searchAnalyzer, similarity, meta, boost);
} }
@ -219,11 +219,12 @@ public final class KeywordFieldMapper extends FieldMapper {
boolean hasNorms; boolean hasNorms;
public KeywordFieldType(String name, boolean isSearchable, boolean hasDocValues, boolean hasNorms, public KeywordFieldType(String name, boolean hasDocValues, FieldType fieldType,
boolean eagerGlobalOrdinals, NamedAnalyzer normalizer, NamedAnalyzer searchAnalyzer, boolean eagerGlobalOrdinals, NamedAnalyzer normalizer, NamedAnalyzer searchAnalyzer,
SimilarityProvider similarity, Map<String, String> meta, float boost) { SimilarityProvider similarity, Map<String, String> meta, float boost) {
super(name, isSearchable, hasDocValues, meta); super(name, fieldType.indexOptions() != IndexOptions.NONE,
this.hasNorms = hasNorms; hasDocValues, new TextSearchInfo(fieldType), meta);
this.hasNorms = fieldType.omitNorms() == false;
setEagerGlobalOrdinals(eagerGlobalOrdinals); setEagerGlobalOrdinals(eagerGlobalOrdinals);
setIndexAnalyzer(normalizer); setIndexAnalyzer(normalizer);
setSearchAnalyzer(searchAnalyzer); setSearchAnalyzer(searchAnalyzer);
@ -232,11 +233,14 @@ public final class KeywordFieldMapper extends FieldMapper {
} }
public KeywordFieldType(String name, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) { public KeywordFieldType(String name, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) {
this(name, isSearchable, hasDocValues, true, false, Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER, null, meta, 1.0f); super(name, isSearchable, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
} }
public KeywordFieldType(String name) { public KeywordFieldType(String name) {
this(name, true, true, Collections.emptyMap()); this(name, true, Defaults.FIELD_TYPE, false,
Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER, null, Collections.emptyMap(), 1f);
} }
protected KeywordFieldType(KeywordFieldType ref) { protected KeywordFieldType(KeywordFieldType ref) {

View File

@ -63,11 +63,11 @@ public abstract class MappedFieldType {
private final String name; private final String name;
private final boolean docValues; private final boolean docValues;
private final boolean isIndexed; private final boolean isIndexed;
private final TextSearchInfo textSearchInfo;
private float boost; private float boost;
private NamedAnalyzer indexAnalyzer; private NamedAnalyzer indexAnalyzer;
private NamedAnalyzer searchAnalyzer; private NamedAnalyzer searchAnalyzer;
private NamedAnalyzer searchQuoteAnalyzer; private NamedAnalyzer searchQuoteAnalyzer;
protected boolean hasPositions;
private SimilarityProvider similarity; private SimilarityProvider similarity;
private boolean eagerGlobalOrdinals; private boolean eagerGlobalOrdinals;
private Map<String, String> meta; private Map<String, String> meta;
@ -83,14 +83,15 @@ public abstract class MappedFieldType {
this.similarity = ref.similarity(); this.similarity = ref.similarity();
this.eagerGlobalOrdinals = ref.eagerGlobalOrdinals; this.eagerGlobalOrdinals = ref.eagerGlobalOrdinals;
this.meta = ref.meta; this.meta = ref.meta;
this.hasPositions = ref.hasPositions; this.textSearchInfo = ref.textSearchInfo;
} }
public MappedFieldType(String name, boolean isIndexed, boolean hasDocValues, Map<String, String> meta) { public MappedFieldType(String name, boolean isIndexed, boolean hasDocValues, TextSearchInfo textSearchInfo, Map<String, String> meta) {
setBoost(1.0f); setBoost(1.0f);
this.name = Objects.requireNonNull(name); this.name = Objects.requireNonNull(name);
this.isIndexed = isIndexed; this.isIndexed = isIndexed;
this.docValues = hasDocValues; this.docValues = hasDocValues;
this.textSearchInfo = Objects.requireNonNull(textSearchInfo);
this.meta = meta; this.meta = meta;
} }
@ -151,10 +152,6 @@ public abstract class MappedFieldType {
this.boost = boost; this.boost = boost;
} }
public boolean hasPositions() {
return hasPositions;
}
public boolean hasDocValues() { public boolean hasDocValues() {
return docValues; return docValues;
} }
@ -411,4 +408,16 @@ public abstract class MappedFieldType {
public void updateMeta(Map<String, String> meta) { public void updateMeta(Map<String, String> meta) {
this.meta = meta; this.meta = meta;
} }
/**
* Returns information on how any text in this field is indexed
*
* Fields that do not support any text-based queries should return
* {@link TextSearchInfo#NONE}. Some fields (eg numeric) may support
* only simple match queries, and can return
* {@link TextSearchInfo#SIMPLE_MATCH_ONLY}
*/
public TextSearchInfo getTextSearchInfo() {
return textSearchInfo;
}
} }

View File

@ -24,7 +24,6 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.message.ParameterizedMessage; import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.DelegatingAnalyzerWrapper; import org.apache.lucene.analysis.DelegatingAnalyzerWrapper;
import org.apache.lucene.document.FieldType;
import org.elasticsearch.Assertions; import org.elasticsearch.Assertions;
import org.elasticsearch.Version; import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetadata; import org.elasticsearch.cluster.metadata.IndexMetadata;
@ -198,20 +197,6 @@ public class MapperService extends AbstractIndexComponent implements Closeable {
return this.documentParser; return this.documentParser;
} }
public FieldType getLuceneFieldType(String field) {
Mapper mapper = documentMapper().mappers().getMapper(field);
if (mapper == null) {
return null;
}
if (mapper instanceof FieldAliasMapper) {
return getLuceneFieldType(((FieldAliasMapper)mapper).path());
}
if (mapper instanceof FieldMapper == false) {
return null;
}
return ((FieldMapper) mapper).fieldType;
}
/** /**
* Parses the mappings (formatted as JSON) into a map * Parses the mappings (formatted as JSON) into a map
*/ */

View File

@ -904,7 +904,7 @@ public class NumberFieldMapper extends FieldMapper {
private final NumberType type; private final NumberType type;
public NumberFieldType(String name, NumberType type, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) { public NumberFieldType(String name, NumberType type, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) {
super(name, isSearchable, hasDocValues, meta); super(name, isSearchable, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
this.type = Objects.requireNonNull(type); this.type = Objects.requireNonNull(type);
this.setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); // allows number fields in significant text aggs - do we need this? this.setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); // allows number fields in significant text aggs - do we need this?
this.setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); // allows match queries on number fields this.setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); // allows match queries on number fields

View File

@ -193,7 +193,7 @@ public class RangeFieldMapper extends FieldMapper {
protected final DateMathParser dateMathParser; protected final DateMathParser dateMathParser;
public RangeFieldType(String name, RangeType type, boolean indexed, boolean hasDocValues, Map<String, String> meta) { public RangeFieldType(String name, RangeType type, boolean indexed, boolean hasDocValues, Map<String, String> meta) {
super(name, indexed, hasDocValues, meta); super(name, indexed, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
assert type != RangeType.DATE; assert type != RangeType.DATE;
this.rangeType = Objects.requireNonNull(type); this.rangeType = Objects.requireNonNull(type);
dateTimeFormatter = null; dateTimeFormatter = null;
@ -207,7 +207,7 @@ public class RangeFieldMapper extends FieldMapper {
} }
public RangeFieldType(String name, boolean indexed, boolean hasDocValues, DateFormatter formatter, Map<String, String> meta) { public RangeFieldType(String name, boolean indexed, boolean hasDocValues, DateFormatter formatter, Map<String, String> meta) {
super(name, indexed, hasDocValues, meta); super(name, indexed, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
this.rangeType = RangeType.DATE; this.rangeType = RangeType.DATE;
this.dateTimeFormatter = Objects.requireNonNull(formatter); this.dateTimeFormatter = Objects.requireNonNull(formatter);
this.dateMathParser = dateTimeFormatter.toDateMathParser(); this.dateMathParser = dateTimeFormatter.toDateMathParser();

View File

@ -110,7 +110,7 @@ public class RoutingFieldMapper extends MetadataFieldMapper {
static RoutingFieldType INSTANCE = new RoutingFieldType(); static RoutingFieldType INSTANCE = new RoutingFieldType();
private RoutingFieldType() { private RoutingFieldType() {
super(NAME, true, false, Collections.emptyMap()); super(NAME, true, false, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
} }

View File

@ -122,7 +122,7 @@ public class SeqNoFieldMapper extends MetadataFieldMapper {
static final class SeqNoFieldType extends SimpleMappedFieldType { static final class SeqNoFieldType extends SimpleMappedFieldType {
SeqNoFieldType() { SeqNoFieldType() {
super(NAME, true, true, Collections.emptyMap()); super(NAME, true, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
} }
protected SeqNoFieldType(SeqNoFieldType ref) { protected SeqNoFieldType(SeqNoFieldType ref) {

View File

@ -32,8 +32,9 @@ import java.util.Map;
*/ */
public abstract class SimpleMappedFieldType extends MappedFieldType { public abstract class SimpleMappedFieldType extends MappedFieldType {
protected SimpleMappedFieldType(String name, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) { protected SimpleMappedFieldType(String name, boolean isSearchable, boolean hasDocValues,
super(name, isSearchable, hasDocValues, meta); TextSearchInfo textSearchInfo, Map<String, String> meta) {
super(name, isSearchable, hasDocValues, textSearchInfo, meta);
} }
protected SimpleMappedFieldType(MappedFieldType ref) { protected SimpleMappedFieldType(MappedFieldType ref) {

View File

@ -149,7 +149,7 @@ public class SourceFieldMapper extends MetadataFieldMapper {
public static final SourceFieldType INSTANCE = new SourceFieldType(); public static final SourceFieldType INSTANCE = new SourceFieldType();
private SourceFieldType() { private SourceFieldType() {
super(NAME, false, false, Collections.emptyMap()); super(NAME, false, false, TextSearchInfo.NONE, Collections.emptyMap());
} }
protected SourceFieldType(SourceFieldType ref) { protected SourceFieldType(SourceFieldType ref) {

View File

@ -50,8 +50,9 @@ public abstract class StringFieldType extends TermBasedFieldType {
private static final Pattern WILDCARD_PATTERN = Pattern.compile("(\\\\.)|([?*]+)"); private static final Pattern WILDCARD_PATTERN = Pattern.compile("(\\\\.)|([?*]+)");
public StringFieldType(String name, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) { public StringFieldType(String name, boolean isSearchable, boolean hasDocValues,
super(name, isSearchable, hasDocValues, meta); TextSearchInfo textSearchInfo, Map<String, String> meta) {
super(name, isSearchable, hasDocValues, textSearchInfo, meta);
} }
protected StringFieldType(MappedFieldType ref) { protected StringFieldType(MappedFieldType ref) {

View File

@ -35,8 +35,8 @@ import java.util.Map;
* with the inverted index. */ * with the inverted index. */
abstract class TermBasedFieldType extends SimpleMappedFieldType { abstract class TermBasedFieldType extends SimpleMappedFieldType {
TermBasedFieldType(String name, boolean isSearchable, boolean hasDocValues, Map<String, String> meta) { TermBasedFieldType(String name, boolean isSearchable, boolean hasDocValues, TextSearchInfo textSearchInfo, Map<String, String> meta) {
super(name, isSearchable, hasDocValues, meta); super(name, isSearchable, hasDocValues, textSearchInfo, meta);
} }
protected TermBasedFieldType(MappedFieldType ref) { protected TermBasedFieldType(MappedFieldType ref) {

View File

@ -187,8 +187,7 @@ public class TextFieldMapper extends FieldMapper {
} }
private TextFieldType buildFieldType(BuilderContext context) { private TextFieldType buildFieldType(BuilderContext context) {
TextFieldType ft = new TextFieldType(buildFullName(context), indexed, TextFieldType ft = new TextFieldType(buildFullName(context), fieldType, meta);
fieldType.indexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0, meta);
ft.setIndexAnalyzer(indexAnalyzer); ft.setIndexAnalyzer(indexAnalyzer);
ft.setSearchAnalyzer(searchAnalyzer); ft.setSearchAnalyzer(searchAnalyzer);
ft.setSearchQuoteAnalyzer(searchQuoteAnalyzer); ft.setSearchQuoteAnalyzer(searchQuoteAnalyzer);
@ -203,7 +202,7 @@ public class TextFieldMapper extends FieldMapper {
return ft; return ft;
} }
private PrefixFieldMapper buildPrefixMapper(BuilderContext context) { private PrefixFieldMapper buildPrefixMapper(BuilderContext context, TextFieldType tft) {
if (minPrefixChars == -1) { if (minPrefixChars == -1) {
return null; return null;
} }
@ -231,7 +230,7 @@ public class TextFieldMapper extends FieldMapper {
if (fieldType.storeTermVectorOffsets()) { if (fieldType.storeTermVectorOffsets()) {
pft.setStoreTermVectorOffsets(true); pft.setStoreTermVectorOffsets(true);
} }
PrefixFieldType prefixFieldType = new PrefixFieldType(fullName, fullName + "._index_prefix", PrefixFieldType prefixFieldType = new PrefixFieldType(tft, fullName + "._index_prefix",
minPrefixChars, maxPrefixChars, pft.indexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0); minPrefixChars, maxPrefixChars, pft.indexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0);
prefixFieldType.setAnalyzer(indexAnalyzer); prefixFieldType.setAnalyzer(indexAnalyzer);
return new PrefixFieldMapper(pft, prefixFieldType); return new PrefixFieldMapper(pft, prefixFieldType);
@ -264,7 +263,7 @@ public class TextFieldMapper extends FieldMapper {
} }
TextFieldType tft = buildFieldType(context); TextFieldType tft = buildFieldType(context);
return new TextFieldMapper(name, return new TextFieldMapper(name,
fieldType, tft, positionIncrementGap, buildPrefixMapper(context), buildPhraseMapper(context, tft), fieldType, tft, positionIncrementGap, buildPrefixMapper(context, tft), buildPhraseMapper(context, tft),
multiFieldsBuilder.build(this, context), copyTo); multiFieldsBuilder.build(this, context), copyTo);
} }
} }
@ -367,7 +366,7 @@ public class TextFieldMapper extends FieldMapper {
final TextFieldType parent; final TextFieldType parent;
PhraseFieldType(TextFieldType parent) { PhraseFieldType(TextFieldType parent) {
super(parent.name() + FAST_PHRASE_SUFFIX, true, false, Collections.emptyMap()); super(parent.name() + FAST_PHRASE_SUFFIX, true, false, parent.getTextSearchInfo(), Collections.emptyMap());
setAnalyzer(parent.indexAnalyzer().name(), parent.indexAnalyzer().analyzer()); setAnalyzer(parent.indexAnalyzer().name(), parent.indexAnalyzer().analyzer());
this.parent = parent; this.parent = parent;
} }
@ -396,10 +395,11 @@ public class TextFieldMapper extends FieldMapper {
final int minChars; final int minChars;
final int maxChars; final int maxChars;
final String parentField; final TextFieldType parentField;
final boolean hasPositions;
PrefixFieldType(String parentField, String name, int minChars, int maxChars, boolean hasPositions) { PrefixFieldType(TextFieldType parentField, String name, int minChars, int maxChars, boolean hasPositions) {
super(name, true, false, Collections.emptyMap()); super(name, true, false, parentField.getTextSearchInfo(), Collections.emptyMap());
this.minChars = minChars; this.minChars = minChars;
this.maxChars = maxChars; this.maxChars = maxChars;
this.parentField = parentField; this.parentField = parentField;
@ -437,7 +437,7 @@ public class TextFieldMapper extends FieldMapper {
query.setRewriteMethod(method); query.setRewriteMethod(method);
return new BooleanQuery.Builder() return new BooleanQuery.Builder()
.add(query, BooleanClause.Occur.SHOULD) .add(query, BooleanClause.Occur.SHOULD)
.add(new TermQuery(new Term(parentField, value)), BooleanClause.Occur.SHOULD) .add(new TermQuery(new Term(parentField.name(), value)), BooleanClause.Occur.SHOULD)
.build(); .build();
} }
@ -556,18 +556,26 @@ public class TextFieldMapper extends FieldMapper {
private int fielddataMinSegmentSize; private int fielddataMinSegmentSize;
private PrefixFieldType prefixFieldType; private PrefixFieldType prefixFieldType;
private boolean indexPhrases = false; private boolean indexPhrases = false;
private final FieldType indexedFieldType;
public TextFieldType(String name, boolean indexed, boolean hasPositions, Map<String, String> meta) { public TextFieldType(String name, FieldType indexedFieldType, Map<String, String> meta) {
super(name, indexed, false, meta); super(name, indexedFieldType.indexOptions() != IndexOptions.NONE, false,
this.hasPositions = hasPositions; new TextSearchInfo(indexedFieldType), meta);
this.indexedFieldType = indexedFieldType;
fielddata = false; fielddata = false;
fielddataMinFrequency = Defaults.FIELDDATA_MIN_FREQUENCY; fielddataMinFrequency = Defaults.FIELDDATA_MIN_FREQUENCY;
fielddataMaxFrequency = Defaults.FIELDDATA_MAX_FREQUENCY; fielddataMaxFrequency = Defaults.FIELDDATA_MAX_FREQUENCY;
fielddataMinSegmentSize = Defaults.FIELDDATA_MIN_SEGMENT_SIZE; fielddataMinSegmentSize = Defaults.FIELDDATA_MIN_SEGMENT_SIZE;
} }
public TextFieldType(String name, boolean indexed, Map<String, String> meta) {
super(name, indexed, false, new TextSearchInfo(Defaults.FIELD_TYPE), meta);
this.indexedFieldType = Defaults.FIELD_TYPE;
fielddata = false;
}
public TextFieldType(String name) { public TextFieldType(String name) {
this(name, true, true, Collections.emptyMap()); this(name, Defaults.FIELD_TYPE, Collections.emptyMap());
} }
protected TextFieldType(TextFieldType ref) { protected TextFieldType(TextFieldType ref) {
@ -580,7 +588,7 @@ public class TextFieldMapper extends FieldMapper {
if (ref.prefixFieldType != null) { if (ref.prefixFieldType != null) {
this.prefixFieldType = ref.prefixFieldType.clone(); this.prefixFieldType = ref.prefixFieldType.clone();
} }
this.hasPositions = ref.hasPositions; this.indexedFieldType = ref.indexedFieldType;
} }
@Override @Override
@ -652,10 +660,6 @@ public class TextFieldMapper extends FieldMapper {
return this.prefixFieldType; return this.prefixFieldType;
} }
public boolean hasPositions() {
return this.hasPositions;
}
@Override @Override
public String typeName() { public String typeName() {
return CONTENT_TYPE; return CONTENT_TYPE;
@ -680,7 +684,7 @@ public class TextFieldMapper extends FieldMapper {
if (prefixFieldType != null if (prefixFieldType != null
&& value.length() >= prefixFieldType.minChars && value.length() >= prefixFieldType.minChars
&& value.length() <= prefixFieldType.maxChars && value.length() <= prefixFieldType.maxChars
&& prefixFieldType.hasPositions()) { && prefixFieldType.getTextSearchInfo().hasPositions()) {
return new FieldMaskingSpanQuery(new SpanTermQuery(new Term(prefixFieldType.name(), indexedValueForSearch(value))), name()); return new FieldMaskingSpanQuery(new SpanTermQuery(new Term(prefixFieldType.name(), indexedValueForSearch(value))), name());
} else { } else {
@ -693,7 +697,7 @@ public class TextFieldMapper extends FieldMapper {
@Override @Override
public Query existsQuery(QueryShardContext context) { public Query existsQuery(QueryShardContext context) {
if (context.getMapperService().getLuceneFieldType(name()).omitNorms()) { if (indexedFieldType.omitNorms()) {
return new TermQuery(new Term(FieldNamesFieldMapper.NAME, name())); return new TermQuery(new Term(FieldNamesFieldMapper.NAME, name()));
} else { } else {
return new NormsFieldExistsQuery(name()); return new NormsFieldExistsQuery(name());
@ -703,7 +707,7 @@ public class TextFieldMapper extends FieldMapper {
@Override @Override
public IntervalsSource intervals(String text, int maxGaps, boolean ordered, public IntervalsSource intervals(String text, int maxGaps, boolean ordered,
NamedAnalyzer analyzer, boolean prefix) throws IOException { NamedAnalyzer analyzer, boolean prefix) throws IOException {
if (hasPositions() == false) { if (getTextSearchInfo().hasPositions() == false) {
throw new IllegalArgumentException("Cannot create intervals over field [" + name() + "] with no positions indexed"); throw new IllegalArgumentException("Cannot create intervals over field [" + name() + "] with no positions indexed");
} }
if (analyzer == null) { if (analyzer == null) {

View File

@ -0,0 +1,114 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.index.mapper;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexOptions;
/**
* Encapsulates information about how to perform text searches over a field
*/
public class TextSearchInfo {
private static final FieldType SIMPLE_MATCH_ONLY_FIELD_TYPE = new FieldType();
static {
SIMPLE_MATCH_ONLY_FIELD_TYPE.setTokenized(false);
SIMPLE_MATCH_ONLY_FIELD_TYPE.setOmitNorms(true);
SIMPLE_MATCH_ONLY_FIELD_TYPE.freeze();
}
/**
* Defines indexing information for fields that support only simple match text queries
*
* Note that the results of {@link #isStored()} for this may not be accurate
*/
public static final TextSearchInfo SIMPLE_MATCH_ONLY = new TextSearchInfo(SIMPLE_MATCH_ONLY_FIELD_TYPE);
/**
* Specifies that this field does not support text searching of any kind
*/
public static final TextSearchInfo NONE = new TextSearchInfo(SIMPLE_MATCH_ONLY_FIELD_TYPE);
private final FieldType luceneFieldType;
/**
* Create a TextSearchInfo by wrapping a lucene FieldType
*/
public TextSearchInfo(FieldType luceneFieldType) {
this.luceneFieldType = luceneFieldType;
}
/**
* @return whether or not this field supports positional queries
*/
public boolean hasPositions() {
return luceneFieldType.indexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS) >= 0;
}
/**
* @return whether or not this field has indexed offsets for highlighting
*/
public boolean hasOffsets() {
return luceneFieldType.indexOptions().compareTo(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) >= 0;
}
/**
* @return whether or not this field has indexed norms
*/
public boolean hasNorms() {
return luceneFieldType.omitNorms() == false;
}
/**
* @return whether or not this field is tokenized
*/
public boolean isTokenized() {
return luceneFieldType.tokenized();
}
/**
* @return whether or not this field is stored
*/
public boolean isStored() {
return luceneFieldType.stored(); // TODO move this directly to MappedFieldType? It's not text specific...
}
/**
* What sort of term vectors are available
*/
public enum TermVector { NONE, DOCS, POSITIONS, OFFSETS }
/**
* @return the type of term vectors available for this field
*/
public TermVector termVectors() {
if (luceneFieldType.storeTermVectors() == false) {
return TermVector.NONE;
}
if (luceneFieldType.storeTermVectorOffsets()) {
return TermVector.OFFSETS;
}
if (luceneFieldType.storeTermVectorPositions()) {
return TermVector.POSITIONS;
}
return TermVector.DOCS;
}
}

View File

@ -101,7 +101,7 @@ public class TypeFieldMapper extends MetadataFieldMapper {
public static final TypeFieldType INSTANCE = new TypeFieldType(); public static final TypeFieldType INSTANCE = new TypeFieldType();
private TypeFieldType() { private TypeFieldType() {
super(NAME, true, false, Collections.emptyMap()); super(NAME, true, false, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
} }
protected TypeFieldType(TypeFieldType ref) { protected TypeFieldType(TypeFieldType ref) {

View File

@ -72,7 +72,7 @@ public class VersionFieldMapper extends MetadataFieldMapper {
public static final VersionFieldType INSTANCE = new VersionFieldType(); public static final VersionFieldType INSTANCE = new VersionFieldType();
private VersionFieldType() { private VersionFieldType() {
super(NAME, false, true, Collections.emptyMap()); super(NAME, false, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
} }
protected VersionFieldType(VersionFieldType ref) { protected VersionFieldType(VersionFieldType ref) {

View File

@ -663,7 +663,7 @@ public abstract class IntervalsSourceProvider implements NamedWriteable, ToXCont
} }
private void checkPositions(MappedFieldType type) { private void checkPositions(MappedFieldType type) {
if (type.hasPositions() == false) { if (type.getTextSearchInfo().hasPositions() == false) {
throw new IllegalArgumentException("Cannot create intervals over field [" + type.name() + "] with no positions indexed"); throw new IllegalArgumentException("Cannot create intervals over field [" + type.name() + "] with no positions indexed");
} }
} }
@ -801,7 +801,7 @@ public abstract class IntervalsSourceProvider implements NamedWriteable, ToXCont
} }
private void checkPositions(MappedFieldType type) { private void checkPositions(MappedFieldType type) {
if (type.hasPositions() == false) { if (type.getTextSearchInfo().hasPositions() == false) {
throw new IllegalArgumentException("Cannot create intervals over field [" + type.name() + "] with no positions indexed"); throw new IllegalArgumentException("Cannot create intervals over field [" + type.name() + "] with no positions indexed");
} }
} }

View File

@ -368,7 +368,7 @@ public class MatchQuery {
super(analyzer); super(analyzer);
this.fieldType = fieldType; this.fieldType = fieldType;
setEnablePositionIncrements(enablePositionIncrements); setEnablePositionIncrements(enablePositionIncrements);
if (fieldType.hasPositions()) { if (fieldType.getTextSearchInfo().hasPositions()) {
setAutoGenerateMultiTermSynonymsPhraseQuery(autoGenerateSynonymsPhraseQuery); setAutoGenerateMultiTermSynonymsPhraseQuery(autoGenerateSynonymsPhraseQuery);
} else { } else {
setAutoGenerateMultiTermSynonymsPhraseQuery(false); setAutoGenerateMultiTermSynonymsPhraseQuery(false);
@ -840,7 +840,7 @@ public class MatchQuery {
} }
private void checkForPositions(String field) { private void checkForPositions(String field) {
if (fieldType.hasPositions() == false) { if (fieldType.getTextSearchInfo().hasPositions() == false) {
throw new IllegalStateException("field:[" + field + "] was indexed without position data; cannot run PhraseQuery"); throw new IllegalStateException("field:[" + field + "] was indexed without position data; cannot run PhraseQuery");
} }
} }

View File

@ -23,7 +23,6 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute; import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.Term; import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.ParseException; import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.Token; import org.apache.lucene.queryparser.classic.Token;
@ -53,6 +52,7 @@ import org.elasticsearch.index.mapper.DateFieldMapper.DateFieldType;
import org.elasticsearch.index.mapper.FieldNamesFieldMapper; import org.elasticsearch.index.mapper.FieldNamesFieldMapper;
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.TextSearchInfo;
import org.elasticsearch.index.query.ExistsQueryBuilder; import org.elasticsearch.index.query.ExistsQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder; import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
@ -518,13 +518,12 @@ public class QueryStringQueryParser extends XQueryParser {
Analyzer oldAnalyzer = getAnalyzer(); Analyzer oldAnalyzer = getAnalyzer();
try { try {
MappedFieldType currentFieldType = context.fieldMapper(field); MappedFieldType currentFieldType = context.fieldMapper(field);
if (currentFieldType == null) { if (currentFieldType == null || currentFieldType.getTextSearchInfo() == TextSearchInfo.NONE) {
return newUnmappedFieldQuery(field); return newUnmappedFieldQuery(field);
} }
setAnalyzer(forceAnalyzer == null ? queryBuilder.context.getSearchAnalyzer(currentFieldType) : forceAnalyzer); setAnalyzer(forceAnalyzer == null ? queryBuilder.context.getSearchAnalyzer(currentFieldType) : forceAnalyzer);
FieldType ft = context.getMapperService().getLuceneFieldType(field);
Query query = null; Query query = null;
if (ft.tokenized() == false) { if (currentFieldType.getTextSearchInfo().isTokenized() == false) {
query = currentFieldType.prefixQuery(termStr, getMultiTermRewriteMethod(), context); query = currentFieldType.prefixQuery(termStr, getMultiTermRewriteMethod(), context);
} else { } else {
query = getPossiblyAnalyzedPrefixQuery(currentFieldType.name(), termStr, currentFieldType); query = getPossiblyAnalyzedPrefixQuery(currentFieldType.name(), termStr, currentFieldType);

View File

@ -51,6 +51,7 @@ import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.index.mapper.SourceFieldMapper;
import org.elasticsearch.index.mapper.SourceToParse; import org.elasticsearch.index.mapper.SourceToParse;
import org.elasticsearch.index.mapper.StringFieldType; import org.elasticsearch.index.mapper.StringFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.mapper.Uid; import org.elasticsearch.index.mapper.Uid;
import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShard;
import org.elasticsearch.search.dfs.AggregatedDfs; import org.elasticsearch.search.dfs.AggregatedDfs;
@ -201,7 +202,7 @@ public class TermVectorsService {
continue; continue;
} }
// already retrieved, only if the analyzer hasn't been overridden at the field // already retrieved, only if the analyzer hasn't been overridden at the field
if (indexShard.mapperService().getLuceneFieldType(field).storeTermVectors() && if (fieldType.getTextSearchInfo().termVectors() != TextSearchInfo.TermVector.NONE &&
(request.perFieldAnalyzer() == null || !request.perFieldAnalyzer().containsKey(field))) { (request.perFieldAnalyzer() == null || !request.perFieldAnalyzer().containsKey(field))) {
continue; continue;
} }

View File

@ -18,7 +18,6 @@
*/ */
package org.elasticsearch.search.fetch.subphase.highlight; package org.elasticsearch.search.fetch.subphase.highlight;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.search.highlight.Encoder; import org.apache.lucene.search.highlight.Encoder;
import org.apache.lucene.search.vectorhighlight.BaseFragmentsBuilder; import org.apache.lucene.search.vectorhighlight.BaseFragmentsBuilder;
import org.apache.lucene.search.vectorhighlight.BoundaryScanner; import org.apache.lucene.search.vectorhighlight.BoundaryScanner;
@ -39,6 +38,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.text.Text; import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.util.CollectionUtils; import org.elasticsearch.common.util.CollectionUtils;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.fetch.FetchPhaseExecutionException; import org.elasticsearch.search.fetch.FetchPhaseExecutionException;
import org.elasticsearch.search.fetch.FetchSubPhase; import org.elasticsearch.search.fetch.FetchSubPhase;
@ -75,11 +75,12 @@ public class FastVectorHighlighter implements Highlighter {
FetchSubPhase.HitContext hitContext = highlighterContext.hitContext; FetchSubPhase.HitContext hitContext = highlighterContext.hitContext;
MappedFieldType fieldType = highlighterContext.fieldType; MappedFieldType fieldType = highlighterContext.fieldType;
if (canHighlight(highlighterContext.luceneFieldType) == false) { if (canHighlight(fieldType) == false) {
throw new IllegalArgumentException("the field [" + highlighterContext.fieldName + throw new IllegalArgumentException("the field [" + highlighterContext.fieldName +
"] should be indexed with term vector with position offsets to be used with fast vector highlighter"); "] should be indexed with term vector with position offsets to be used with fast vector highlighter");
} }
TextSearchInfo tsi = fieldType.getTextSearchInfo();
Encoder encoder = field.fieldOptions().encoder().equals("html") ? Encoder encoder = field.fieldOptions().encoder().equals("html") ?
HighlightUtils.Encoders.HTML : HighlightUtils.Encoders.DEFAULT; HighlightUtils.Encoders.HTML : HighlightUtils.Encoders.DEFAULT;
@ -99,7 +100,7 @@ public class FastVectorHighlighter implements Highlighter {
if (field.fieldOptions().numberOfFragments() == 0) { if (field.fieldOptions().numberOfFragments() == 0) {
fragListBuilder = new SingleFragListBuilder(); fragListBuilder = new SingleFragListBuilder();
if (!forceSource && highlighterContext.luceneFieldType.stored()) { if (!forceSource && tsi.isStored()) {
fragmentsBuilder = new SimpleFragmentsBuilder(fieldType, field.fieldOptions().preTags(), fragmentsBuilder = new SimpleFragmentsBuilder(fieldType, field.fieldOptions().preTags(),
field.fieldOptions().postTags(), boundaryScanner); field.fieldOptions().postTags(), boundaryScanner);
} else { } else {
@ -110,7 +111,7 @@ public class FastVectorHighlighter implements Highlighter {
fragListBuilder = field.fieldOptions().fragmentOffset() == -1 ? fragListBuilder = field.fieldOptions().fragmentOffset() == -1 ?
new SimpleFragListBuilder() : new SimpleFragListBuilder(field.fieldOptions().fragmentOffset()); new SimpleFragListBuilder() : new SimpleFragListBuilder(field.fieldOptions().fragmentOffset());
if (field.fieldOptions().scoreOrdered()) { if (field.fieldOptions().scoreOrdered()) {
if (!forceSource && highlighterContext.luceneFieldType.stored()) { if (!forceSource && tsi.isStored()) {
fragmentsBuilder = new ScoreOrderFragmentsBuilder(field.fieldOptions().preTags(), fragmentsBuilder = new ScoreOrderFragmentsBuilder(field.fieldOptions().preTags(),
field.fieldOptions().postTags(), boundaryScanner); field.fieldOptions().postTags(), boundaryScanner);
} else { } else {
@ -118,7 +119,7 @@ public class FastVectorHighlighter implements Highlighter {
field.fieldOptions().preTags(), field.fieldOptions().postTags(), boundaryScanner); field.fieldOptions().preTags(), field.fieldOptions().postTags(), boundaryScanner);
} }
} else { } else {
if (!forceSource && highlighterContext.luceneFieldType.stored()) { if (!forceSource && tsi.isStored()) {
fragmentsBuilder = new SimpleFragmentsBuilder(fieldType, field.fieldOptions().preTags(), fragmentsBuilder = new SimpleFragmentsBuilder(fieldType, field.fieldOptions().preTags(),
field.fieldOptions().postTags(), boundaryScanner); field.fieldOptions().postTags(), boundaryScanner);
} else { } else {
@ -211,10 +212,8 @@ public class FastVectorHighlighter implements Highlighter {
} }
@Override @Override
public boolean canHighlight(FieldType fieldType) { public boolean canHighlight(MappedFieldType ft) {
return fieldType.storeTermVectors() return ft.getTextSearchInfo().termVectors() == TextSearchInfo.TermVector.OFFSETS;
&& fieldType.storeTermVectorOffsets()
&& fieldType.storeTermVectorPositions();
} }
private static BoundaryScanner getBoundaryScanner(Field field) { private static BoundaryScanner getBoundaryScanner(Field field) {

View File

@ -108,10 +108,9 @@ public class HighlightPhase implements FetchSubPhase {
highlightQuery = query; highlightQuery = query;
} }
HighlighterContext highlighterContext = new HighlighterContext(fieldType.name(), HighlighterContext highlighterContext = new HighlighterContext(fieldType.name(),
field, fieldType, shardTarget, context, highlight, hitContext, highlightQuery, field, fieldType, shardTarget, context, highlight, hitContext, highlightQuery);
context.getMapperService().getLuceneFieldType(fieldType.name()));
if ((highlighter.canHighlight(highlighterContext.luceneFieldType) == false) && fieldNameContainsWildcards) { if ((highlighter.canHighlight(fieldType) == false) && fieldNameContainsWildcards) {
// if several fieldnames matched the wildcard then we want to skip those that we cannot highlight // if several fieldnames matched the wildcard then we want to skip those that we cannot highlight
continue; continue;
} }

View File

@ -18,12 +18,12 @@
*/ */
package org.elasticsearch.search.fetch.subphase.highlight; package org.elasticsearch.search.fetch.subphase.highlight;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.search.highlight.DefaultEncoder; import org.apache.lucene.search.highlight.DefaultEncoder;
import org.apache.lucene.search.highlight.Encoder; import org.apache.lucene.search.highlight.Encoder;
import org.apache.lucene.search.highlight.SimpleHTMLEncoder; import org.apache.lucene.search.highlight.SimpleHTMLEncoder;
import org.elasticsearch.index.fieldvisitor.CustomFieldsVisitor; import org.elasticsearch.index.fieldvisitor.CustomFieldsVisitor;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.fetch.FetchSubPhase; import org.elasticsearch.search.fetch.FetchSubPhase;
import org.elasticsearch.search.lookup.SourceLookup; import org.elasticsearch.search.lookup.SourceLookup;
@ -53,8 +53,8 @@ public final class HighlightUtils {
boolean forceSource) throws IOException { boolean forceSource) throws IOException {
//percolator needs to always load from source, thus it sets the global force source to true //percolator needs to always load from source, thus it sets the global force source to true
List<Object> textsToHighlight; List<Object> textsToHighlight;
FieldType luceneFieldType = context.getMapperService().getLuceneFieldType(fieldType.name()); TextSearchInfo tsi = fieldType.getTextSearchInfo();
if (forceSource == false && luceneFieldType.stored()) { if (forceSource == false && tsi.isStored()) {
CustomFieldsVisitor fieldVisitor = new CustomFieldsVisitor(singleton(fieldType.name()), false); CustomFieldsVisitor fieldVisitor = new CustomFieldsVisitor(singleton(fieldType.name()), false);
hitContext.reader().document(hitContext.docId(), fieldVisitor); hitContext.reader().document(hitContext.docId(), fieldVisitor);
textsToHighlight = fieldVisitor.fields().get(fieldType.name()); textsToHighlight = fieldVisitor.fields().get(fieldType.name());

View File

@ -18,7 +18,7 @@
*/ */
package org.elasticsearch.search.fetch.subphase.highlight; package org.elasticsearch.search.fetch.subphase.highlight;
import org.apache.lucene.document.FieldType; import org.elasticsearch.index.mapper.MappedFieldType;
/** /**
* Highlights a search result. * Highlights a search result.
@ -27,5 +27,5 @@ public interface Highlighter {
HighlightField highlight(HighlighterContext highlighterContext); HighlightField highlight(HighlighterContext highlighterContext);
boolean canHighlight(FieldType fieldType); boolean canHighlight(MappedFieldType fieldType);
} }

View File

@ -18,7 +18,6 @@
*/ */
package org.elasticsearch.search.fetch.subphase.highlight; package org.elasticsearch.search.fetch.subphase.highlight;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.search.Query; import org.apache.lucene.search.Query;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
@ -35,7 +34,6 @@ public class HighlighterContext {
public final SearchContextHighlight highlight; public final SearchContextHighlight highlight;
public final FetchSubPhase.HitContext hitContext; public final FetchSubPhase.HitContext hitContext;
public final Query query; public final Query query;
public final FieldType luceneFieldType;
public HighlighterContext(String fieldName, public HighlighterContext(String fieldName,
SearchContextHighlight.Field field, SearchContextHighlight.Field field,
@ -44,7 +42,7 @@ public class HighlighterContext {
QueryShardContext context, QueryShardContext context,
SearchContextHighlight highlight, SearchContextHighlight highlight,
FetchSubPhase.HitContext hitContext, FetchSubPhase.HitContext hitContext,
Query query, FieldType luceneFieldType) { Query query) {
this.fieldName = fieldName; this.fieldName = fieldName;
this.field = field; this.field = field;
this.fieldType = fieldType; this.fieldType = fieldType;
@ -53,6 +51,5 @@ public class HighlighterContext {
this.highlight = highlight; this.highlight = highlight;
this.hitContext = hitContext; this.hitContext = hitContext;
this.query = query; this.query = query;
this.luceneFieldType = luceneFieldType;
} }
} }

View File

@ -22,7 +22,6 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute; import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.search.highlight.Encoder; import org.apache.lucene.search.highlight.Encoder;
import org.apache.lucene.search.highlight.Formatter; import org.apache.lucene.search.highlight.Formatter;
import org.apache.lucene.search.highlight.Fragmenter; import org.apache.lucene.search.highlight.Fragmenter;
@ -203,7 +202,7 @@ public class PlainHighlighter implements Highlighter {
} }
@Override @Override
public boolean canHighlight(FieldType fieldType) { public boolean canHighlight(MappedFieldType fieldType) {
return true; return true;
} }

View File

@ -19,9 +19,6 @@
package org.elasticsearch.search.fetch.subphase.highlight; package org.elasticsearch.search.fetch.subphase.highlight;
import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.FieldInfo;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.highlight.Encoder; import org.apache.lucene.search.highlight.Encoder;
import org.apache.lucene.search.uhighlight.BoundedBreakIteratorScanner; import org.apache.lucene.search.uhighlight.BoundedBreakIteratorScanner;
@ -40,6 +37,7 @@ import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.IdFieldMapper; import org.elasticsearch.index.mapper.IdFieldMapper;
import org.elasticsearch.index.mapper.KeywordFieldMapper; import org.elasticsearch.index.mapper.KeywordFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.fetch.FetchPhaseExecutionException; import org.elasticsearch.search.fetch.FetchPhaseExecutionException;
import org.elasticsearch.search.fetch.FetchSubPhase; import org.elasticsearch.search.fetch.FetchSubPhase;
@ -56,7 +54,7 @@ import static org.apache.lucene.search.uhighlight.CustomUnifiedHighlighter.MULTI
public class UnifiedHighlighter implements Highlighter { public class UnifiedHighlighter implements Highlighter {
@Override @Override
public boolean canHighlight(FieldType fieldType) { public boolean canHighlight(MappedFieldType fieldType) {
return true; return true;
} }
@ -89,8 +87,7 @@ public class UnifiedHighlighter implements Highlighter {
final IndexSearcher searcher = new IndexSearcher(hitContext.reader()); final IndexSearcher searcher = new IndexSearcher(hitContext.reader());
final CustomUnifiedHighlighter highlighter; final CustomUnifiedHighlighter highlighter;
final String fieldValue = mergeFieldValues(fieldValues, MULTIVAL_SEP_CHAR); final String fieldValue = mergeFieldValues(fieldValues, MULTIVAL_SEP_CHAR);
FieldInfo fi = hitContext.reader().getFieldInfos().fieldInfo(field.field()); final OffsetSource offsetSource = getOffsetSource(fieldType);
final OffsetSource offsetSource = getOffsetSource(highlighterContext.luceneFieldType);
int fieldValueLength = fieldValue.length(); int fieldValueLength = fieldValue.length();
if (keywordIgnoreAbove != null && fieldValueLength > keywordIgnoreAbove) { if (keywordIgnoreAbove != null && fieldValueLength > keywordIgnoreAbove) {
return null; // skip highlighting keyword terms that were ignored during indexing return null; // skip highlighting keyword terms that were ignored during indexing
@ -105,7 +102,7 @@ public class UnifiedHighlighter implements Highlighter {
} }
if (numberOfFragments == 0 if (numberOfFragments == 0
// non-tokenized fields should not use any break iterator (ignore boundaryScannerType) // non-tokenized fields should not use any break iterator (ignore boundaryScannerType)
|| highlighterContext.luceneFieldType.tokenized() == false) { || fieldType.getTextSearchInfo().isTokenized() == false) {
// we use a control char to separate values, which is the only char that the custom break iterator // we use a control char to separate values, which is the only char that the custom break iterator
// breaks the text on, so we don't lose the distinction between the different values of a field and we // breaks the text on, so we don't lose the distinction between the different values of a field and we
// get back a snippet per value // get back a snippet per value
@ -220,11 +217,13 @@ public class UnifiedHighlighter implements Highlighter {
return rawValue.substring(0, Math.min(rawValue.length(), Integer.MAX_VALUE - 1)); return rawValue.substring(0, Math.min(rawValue.length(), Integer.MAX_VALUE - 1));
} }
protected OffsetSource getOffsetSource(FieldType fieldType) { protected OffsetSource getOffsetSource(MappedFieldType fieldType) {
if (fieldType.indexOptions() == IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS) { TextSearchInfo tsi = fieldType.getTextSearchInfo();
return fieldType.storeTermVectors() ? OffsetSource.POSTINGS_WITH_TERM_VECTORS : OffsetSource.POSTINGS; if (tsi.hasOffsets()) {
return tsi.termVectors() != TextSearchInfo.TermVector.NONE
? OffsetSource.POSTINGS_WITH_TERM_VECTORS : OffsetSource.POSTINGS;
} }
if (fieldType.storeTermVectorOffsets()) { if (tsi.termVectors() == TextSearchInfo.TermVector.OFFSETS) {
return OffsetSource.TERM_VECTORS; return OffsetSource.TERM_VECTORS;
} }
return OffsetSource.ANALYSIS; return OffsetSource.ANALYSIS;

View File

@ -390,7 +390,8 @@ public class DateFieldMapperTests extends FieldMapperTestCase<DateFieldMapper.Bu
MapperService.MergeReason.MAPPING_UPDATE); MapperService.MergeReason.MAPPING_UPDATE);
assertThat(indexService.mapperService().fieldType("release_date"), notNullValue()); assertThat(indexService.mapperService().fieldType("release_date"), notNullValue());
assertFalse(indexService.mapperService().getLuceneFieldType("release_date").stored()); assertFalse(indexService.mapperService().fieldType("release_date")
.getTextSearchInfo().isStored());
String updateFormatMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("movie") String updateFormatMapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("movie")
.startObject("properties") .startObject("properties")

View File

@ -73,7 +73,7 @@ public class DocumentFieldMapperTests extends LuceneTestCase {
static class FakeFieldType extends TermBasedFieldType { static class FakeFieldType extends TermBasedFieldType {
FakeFieldType(String name) { FakeFieldType(String name) {
super(name, true, true, Collections.emptyMap()); super(name, true, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
} }
FakeFieldType(FakeFieldType other) { FakeFieldType(FakeFieldType other) {

View File

@ -127,7 +127,7 @@ public class ExternalMapper extends FieldMapper {
static class ExternalFieldType extends TermBasedFieldType { static class ExternalFieldType extends TermBasedFieldType {
ExternalFieldType(String name, boolean indexed, boolean hasDocValues) { ExternalFieldType(String name, boolean indexed, boolean hasDocValues) {
super(name, indexed, hasDocValues, Collections.emptyMap()); super(name, indexed, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
} }
protected ExternalFieldType(ExternalFieldType ref) { protected ExternalFieldType(ExternalFieldType ref) {

View File

@ -86,7 +86,7 @@ public class FakeStringFieldMapper extends FieldMapper {
public FakeStringFieldType(String name) { public FakeStringFieldType(String name) {
super(name, true, true, Collections.emptyMap()); super(name, true, true, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
setIndexAnalyzer(Lucene.STANDARD_ANALYZER); setIndexAnalyzer(Lucene.STANDARD_ANALYZER);
setSearchAnalyzer(Lucene.STANDARD_ANALYZER); setSearchAnalyzer(Lucene.STANDARD_ANALYZER);
} }

View File

@ -19,7 +19,6 @@
package org.elasticsearch.index.mapper; package org.elasticsearch.index.mapper;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.IndexableField;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
@ -51,16 +50,12 @@ public class GenericStoreDynamicTemplateTests extends ESSingleNodeTestCase {
assertThat(f.stringValue(), equalTo("some name")); assertThat(f.stringValue(), equalTo("some name"));
assertThat(f.fieldType().stored(), equalTo(true)); assertThat(f.fieldType().stored(), equalTo(true));
FieldType fieldType = mapperService.getLuceneFieldType("name"); assertTrue(mapperService.fieldType("name").getTextSearchInfo().isStored());
assertThat(fieldType.stored(), equalTo(true));
boolean stored = false; boolean stored = false;
for (IndexableField field : doc.getFields("age")) { for (IndexableField field : doc.getFields("age")) {
stored |= field.fieldType().stored(); stored |= field.fieldType().stored();
} }
assertTrue(stored); assertTrue(stored);
fieldType = mapperService.getLuceneFieldType("age");
assertThat(fieldType.stored(), equalTo(true));
} }
} }

View File

@ -19,7 +19,6 @@
package org.elasticsearch.index.mapper; package org.elasticsearch.index.mapper;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.IndexableField;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.compress.CompressedXContent; import org.elasticsearch.common.compress.CompressedXContent;
@ -40,7 +39,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase {
mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE); mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name").indexOptions()); assertTrue(mapperService.fieldType("name").isSearchable());
assertThat(mapperService.fieldType("name.indexed"), nullValue()); assertThat(mapperService.fieldType("name.indexed"), nullValue());
BytesReference json = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().field("name", "some name").endObject()); BytesReference json = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().field("name", "some name").endObject());
@ -54,7 +53,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase {
mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping2.json"); mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping2.json");
mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE); mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name").indexOptions()); assertTrue(mapperService.fieldType("name").isSearchable());
assertThat(mapperService.fieldType("name.indexed"), notNullValue()); assertThat(mapperService.fieldType("name.indexed"), notNullValue());
assertThat(mapperService.fieldType("name.not_indexed"), notNullValue()); assertThat(mapperService.fieldType("name.not_indexed"), notNullValue());
@ -70,7 +69,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase {
mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping3.json"); mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping3.json");
mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE); mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name").indexOptions()); assertTrue(mapperService.fieldType("name").isSearchable());
assertThat(mapperService.fieldType("name.indexed"), notNullValue()); assertThat(mapperService.fieldType("name.indexed"), notNullValue());
assertThat(mapperService.fieldType("name.not_indexed"), notNullValue()); assertThat(mapperService.fieldType("name.not_indexed"), notNullValue());
@ -80,7 +79,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase {
mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping4.json"); mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/test-mapping4.json");
mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE); mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name").indexOptions()); assertTrue(mapperService.fieldType("name").isSearchable());
assertThat(mapperService.fieldType("name.indexed"), notNullValue()); assertThat(mapperService.fieldType("name.indexed"), notNullValue());
assertThat(mapperService.fieldType("name.not_indexed"), notNullValue()); assertThat(mapperService.fieldType("name.not_indexed"), notNullValue());
@ -94,7 +93,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase {
mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE); mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name").indexOptions()); assertTrue(mapperService.fieldType("name").isSearchable());
assertThat(mapperService.fieldType("name.indexed"), nullValue()); assertThat(mapperService.fieldType("name.indexed"), nullValue());
BytesReference json = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().field("name", "some name").endObject()); BytesReference json = BytesReference.bytes(XContentFactory.jsonBuilder().startObject().field("name", "some name").endObject());
@ -109,7 +108,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase {
mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/upgrade1.json"); mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/upgrade1.json");
mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE); mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name").indexOptions()); assertTrue(mapperService.fieldType("name").isSearchable());
assertThat(mapperService.fieldType("name.indexed"), notNullValue()); assertThat(mapperService.fieldType("name.indexed"), notNullValue());
assertThat(mapperService.fieldType("name.not_indexed"), notNullValue()); assertThat(mapperService.fieldType("name.not_indexed"), notNullValue());
@ -126,7 +125,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase {
mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/upgrade2.json"); mapping = copyToStringFromClasspath("/org/elasticsearch/index/mapper/multifield/merge/upgrade2.json");
mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE); mapperService.merge("person", new CompressedXContent(mapping), MapperService.MergeReason.MAPPING_UPDATE);
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name").indexOptions()); assertTrue(mapperService.fieldType("name").isSearchable());
assertThat(mapperService.fieldType("name.indexed"), notNullValue()); assertThat(mapperService.fieldType("name.indexed"), notNullValue());
assertThat(mapperService.fieldType("name.not_indexed"), notNullValue()); assertThat(mapperService.fieldType("name.not_indexed"), notNullValue());
@ -144,7 +143,7 @@ public class JavaMultiFieldMergeTests extends ESSingleNodeTestCase {
} }
// There are conflicts, so the `name.not_indexed3` has not been added // There are conflicts, so the `name.not_indexed3` has not been added
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name").indexOptions()); assertTrue(mapperService.fieldType("name").isSearchable());
assertThat(mapperService.fieldType("name.indexed"), notNullValue()); assertThat(mapperService.fieldType("name.indexed"), notNullValue());
assertThat(mapperService.fieldType("name.not_indexed"), notNullValue()); assertThat(mapperService.fieldType("name.not_indexed"), notNullValue());
assertThat(mapperService.fieldType("name.not_indexed2"), notNullValue()); assertThat(mapperService.fieldType("name.not_indexed2"), notNullValue());

View File

@ -93,35 +93,36 @@ public class MultiFieldTests extends ESSingleNodeTestCase {
assertThat(mapperService.fieldType("name"), notNullValue()); assertThat(mapperService.fieldType("name"), notNullValue());
assertThat(mapperService.fieldType("name"), instanceOf(TextFieldType.class)); assertThat(mapperService.fieldType("name"), instanceOf(TextFieldType.class));
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name").indexOptions()); assertTrue(mapperService.fieldType("name").isSearchable());
assertThat(mapperService.getLuceneFieldType("name").stored(), equalTo(true)); assertTrue(mapperService.fieldType("name").getTextSearchInfo().isStored());
assertThat(mapperService.getLuceneFieldType("name").tokenized(), equalTo(true)); assertTrue(mapperService.fieldType("name").getTextSearchInfo().isTokenized());
assertThat(mapperService.fieldType("name.indexed"), notNullValue()); assertThat(mapperService.fieldType("name.indexed"), notNullValue());
assertThat(mapperService.fieldType("name"), instanceOf(TextFieldType.class)); assertThat(mapperService.fieldType("name"), instanceOf(TextFieldType.class));
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name.indexed").indexOptions()); assertTrue(mapperService.fieldType("name.indexed").isSearchable());
assertThat(mapperService.getLuceneFieldType("name.indexed").stored(), equalTo(false)); assertFalse(mapperService.fieldType("name.indexed").getTextSearchInfo().isStored());
assertThat(mapperService.getLuceneFieldType("name.indexed").tokenized(), equalTo(true)); assertTrue(mapperService.fieldType("name.indexed").getTextSearchInfo().isTokenized());
assertThat(mapperService.fieldType("name.not_indexed"), notNullValue()); assertThat(mapperService.fieldType("name.not_indexed"), notNullValue());
assertThat(mapperService.fieldType("name"), instanceOf(TextFieldType.class)); assertThat(mapperService.fieldType("name"), instanceOf(TextFieldType.class));
assertEquals(IndexOptions.NONE, mapperService.getLuceneFieldType("name.not_indexed").indexOptions()); assertFalse(mapperService.fieldType("name.not_indexed").isSearchable());
assertThat(mapperService.getLuceneFieldType("name.not_indexed").stored(), equalTo(true)); assertTrue(mapperService.fieldType("name.not_indexed").getTextSearchInfo().isStored());
assertThat(mapperService.getLuceneFieldType("name.not_indexed").tokenized(), equalTo(true)); assertTrue(mapperService.fieldType("name.not_indexed").getTextSearchInfo().isTokenized());
assertThat(mapperService.fieldType("name.test1"), notNullValue()); assertThat(mapperService.fieldType("name.test1"), notNullValue());
assertThat(mapperService.fieldType("name"), instanceOf(TextFieldType.class)); assertThat(mapperService.fieldType("name"), instanceOf(TextFieldType.class));
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("name.test1").indexOptions()); assertTrue(mapperService.fieldType("name.test1").isSearchable());
assertThat(mapperService.getLuceneFieldType("name.test1").stored(), equalTo(true)); assertTrue(mapperService.fieldType("name.test1").getTextSearchInfo().isStored());
assertThat(mapperService.getLuceneFieldType("name.test1").tokenized(), equalTo(true)); assertTrue(mapperService.fieldType("name.test1").getTextSearchInfo().isTokenized());
assertThat(mapperService.fieldType("name.test1").eagerGlobalOrdinals(), equalTo(true)); assertThat(mapperService.fieldType("name.test1").eagerGlobalOrdinals(), equalTo(true));
assertThat(mapperService.fieldType("object1.multi1"), notNullValue()); assertThat(mapperService.fieldType("object1.multi1"), notNullValue());
assertThat(mapperService.fieldType("object1.multi1"), instanceOf(DateFieldMapper.DateFieldType.class)); assertThat(mapperService.fieldType("object1.multi1"), instanceOf(DateFieldMapper.DateFieldType.class));
assertThat(mapperService.fieldType("object1.multi1.string"), notNullValue()); assertThat(mapperService.fieldType("object1.multi1.string"), notNullValue());
assertThat(mapperService.fieldType("object1.multi1.string"), instanceOf(KeywordFieldMapper.KeywordFieldType.class)); assertThat(mapperService.fieldType("object1.multi1.string"), instanceOf(KeywordFieldMapper.KeywordFieldType.class));
assertNotSame(IndexOptions.NONE, mapperService.getLuceneFieldType("object1.multi1.string").indexOptions()); assertTrue(mapperService.fieldType("object1.multi1.string").isSearchable());
assertThat(mapperService.getLuceneFieldType("object1.multi1.string").tokenized(), equalTo(false)); assertNotNull(mapperService.fieldType("object1.multi1.string").getTextSearchInfo());
assertFalse(mapperService.fieldType("object1.multi1.string").getTextSearchInfo().isTokenized());
} }
public void testBuildThenParse() throws Exception { public void testBuildThenParse() throws Exception {

View File

@ -19,7 +19,6 @@
package org.elasticsearch.index.mapper; package org.elasticsearch.index.mapper;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.IndexableField;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
@ -51,26 +50,21 @@ public class PathMatchDynamicTemplateTests extends ESSingleNodeTestCase {
assertThat(f.stringValue(), equalTo("top_level")); assertThat(f.stringValue(), equalTo("top_level"));
assertThat(f.fieldType().stored(), equalTo(false)); assertThat(f.fieldType().stored(), equalTo(false));
FieldType fieldType = mapperService.getLuceneFieldType("name"); assertThat(mapperService.fieldType("name").getTextSearchInfo().isStored(), equalTo(false));
assertThat(fieldType.stored(), equalTo(false));
f = doc.getField("obj1.name"); f = doc.getField("obj1.name");
assertThat(f.name(), equalTo("obj1.name")); assertThat(f.name(), equalTo("obj1.name"));
assertThat(f.fieldType().stored(), equalTo(true)); assertThat(f.fieldType().stored(), equalTo(true));
fieldType = mapperService.getLuceneFieldType("obj1.name"); assertThat(mapperService.fieldType("obj1.name").getTextSearchInfo().isStored(), equalTo(true));
assertThat(fieldType.stored(), equalTo(true));
f = doc.getField("obj1.obj2.name"); f = doc.getField("obj1.obj2.name");
assertThat(f.name(), equalTo("obj1.obj2.name")); assertThat(f.name(), equalTo("obj1.obj2.name"));
assertThat(f.fieldType().stored(), equalTo(false)); assertThat(f.fieldType().stored(), equalTo(false));
fieldType = mapperService.getLuceneFieldType("obj1.obj2.name"); assertThat(mapperService.fieldType("obj1.obj2.name").getTextSearchInfo().isStored(), equalTo(false));
assertThat(fieldType.stored(), equalTo(false));
// verify more complex path_match expressions // verify more complex path_match expressions
assertNotNull(mapperService.fieldType("obj3.obj4.prop1").getTextSearchInfo());
fieldType = mapperService.getLuceneFieldType("obj3.obj4.prop1");
assertNotNull(fieldType);
} }
} }

View File

@ -77,14 +77,14 @@ public class TextFieldTypeTests extends FieldTypeTestCase<TextFieldType> {
@Override @Override
protected TextFieldType createDefaultFieldType(String name, Map<String, String> meta) { protected TextFieldType createDefaultFieldType(String name, Map<String, String> meta) {
return new TextFieldType(name, true, true, meta); return new TextFieldType(name, true, meta);
} }
public void testTermQuery() { public void testTermQuery() {
MappedFieldType ft = new TextFieldType("field"); MappedFieldType ft = new TextFieldType("field");
assertEquals(new TermQuery(new Term("field", "foo")), ft.termQuery("foo", null)); assertEquals(new TermQuery(new Term("field", "foo")), ft.termQuery("foo", null));
MappedFieldType unsearchable = new TextFieldType("field", false, true, Collections.emptyMap()); MappedFieldType unsearchable = new TextFieldType("field", false, Collections.emptyMap());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> unsearchable.termQuery("bar", null)); () -> unsearchable.termQuery("bar", null));
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage()); assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
@ -98,7 +98,7 @@ public class TextFieldTypeTests extends FieldTypeTestCase<TextFieldType> {
assertEquals(new TermInSetQuery("field", terms), assertEquals(new TermInSetQuery("field", terms),
ft.termsQuery(Arrays.asList("foo", "bar"), null)); ft.termsQuery(Arrays.asList("foo", "bar"), null));
MappedFieldType unsearchable = new TextFieldType("field", false, true, Collections.emptyMap()); MappedFieldType unsearchable = new TextFieldType("field", false, Collections.emptyMap());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> unsearchable.termsQuery(Arrays.asList("foo", "bar"), null)); () -> unsearchable.termsQuery(Arrays.asList("foo", "bar"), null));
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage()); assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
@ -120,7 +120,7 @@ public class TextFieldTypeTests extends FieldTypeTestCase<TextFieldType> {
assertEquals(new RegexpQuery(new Term("field","foo.*")), assertEquals(new RegexpQuery(new Term("field","foo.*")),
ft.regexpQuery("foo.*", 0, 10, null, MOCK_QSC)); ft.regexpQuery("foo.*", 0, 10, null, MOCK_QSC));
MappedFieldType unsearchable = new TextFieldType("field", false, true, Collections.emptyMap()); MappedFieldType unsearchable = new TextFieldType("field", false, Collections.emptyMap());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> unsearchable.regexpQuery("foo.*", 0, 10, null, MOCK_QSC)); () -> unsearchable.regexpQuery("foo.*", 0, 10, null, MOCK_QSC));
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage()); assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
@ -136,7 +136,7 @@ public class TextFieldTypeTests extends FieldTypeTestCase<TextFieldType> {
assertEquals(new FuzzyQuery(new Term("field","foo"), 2, 1, 50, true), assertEquals(new FuzzyQuery(new Term("field","foo"), 2, 1, 50, true),
ft.fuzzyQuery("foo", Fuzziness.fromEdits(2), 1, 50, true, MOCK_QSC)); ft.fuzzyQuery("foo", Fuzziness.fromEdits(2), 1, 50, true, MOCK_QSC));
MappedFieldType unsearchable = new TextFieldType("field", false, true, Collections.emptyMap()); MappedFieldType unsearchable = new TextFieldType("field", false, Collections.emptyMap());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> unsearchable.fuzzyQuery("foo", Fuzziness.fromEdits(2), 1, 50, true, MOCK_QSC)); () -> unsearchable.fuzzyQuery("foo", Fuzziness.fromEdits(2), 1, 50, true, MOCK_QSC));
assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage()); assertEquals("Cannot search on field [field] since it is not indexed.", e.getMessage());
@ -150,7 +150,7 @@ public class TextFieldTypeTests extends FieldTypeTestCase<TextFieldType> {
public void testIndexPrefixes() { public void testIndexPrefixes() {
TextFieldType ft = new TextFieldType("field"); TextFieldType ft = new TextFieldType("field");
ft.setPrefixFieldType(new TextFieldMapper.PrefixFieldType("field", "field._index_prefix", 2, 10, true)); ft.setPrefixFieldType(new TextFieldMapper.PrefixFieldType(ft, "field._index_prefix", 2, 10, true));
Query q = ft.prefixQuery("goin", CONSTANT_SCORE_REWRITE, randomMockShardContext()); Query q = ft.prefixQuery("goin", CONSTANT_SCORE_REWRITE, randomMockShardContext());
assertEquals(new ConstantScoreQuery(new TermQuery(new Term("field._index_prefix", "goin"))), q); assertEquals(new ConstantScoreQuery(new TermQuery(new Term("field._index_prefix", "goin"))), q);

View File

@ -104,7 +104,7 @@ public class ExistsQueryBuilderTests extends AbstractQueryTestCase<ExistsQueryBu
assertThat(constantScoreQuery.getQuery(), instanceOf(DocValuesFieldExistsQuery.class)); assertThat(constantScoreQuery.getQuery(), instanceOf(DocValuesFieldExistsQuery.class));
DocValuesFieldExistsQuery dvExistsQuery = (DocValuesFieldExistsQuery) constantScoreQuery.getQuery(); DocValuesFieldExistsQuery dvExistsQuery = (DocValuesFieldExistsQuery) constantScoreQuery.getQuery();
assertEquals(field, dvExistsQuery.getField()); assertEquals(field, dvExistsQuery.getField());
} else if (context.getMapperService().getLuceneFieldType(field).omitNorms() == false) { } else if (context.getMapperService().fieldType(field).getTextSearchInfo().hasNorms()) {
assertThat(constantScoreQuery.getQuery(), instanceOf(NormsFieldExistsQuery.class)); assertThat(constantScoreQuery.getQuery(), instanceOf(NormsFieldExistsQuery.class));
NormsFieldExistsQuery normsExistsQuery = (NormsFieldExistsQuery) constantScoreQuery.getQuery(); NormsFieldExistsQuery normsExistsQuery = (NormsFieldExistsQuery) constantScoreQuery.getQuery();
assertEquals(field, normsExistsQuery.getField()); assertEquals(field, normsExistsQuery.getField());

View File

@ -1046,7 +1046,7 @@ public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStr
QueryStringQueryBuilder queryBuilder = new QueryStringQueryBuilder(TEXT_FIELD_NAME + ":*"); QueryStringQueryBuilder queryBuilder = new QueryStringQueryBuilder(TEXT_FIELD_NAME + ":*");
Query query = queryBuilder.toQuery(context); Query query = queryBuilder.toQuery(context);
if (context.getIndexSettings().getIndexVersionCreated().onOrAfter(Version.V_6_1_0) if (context.getIndexSettings().getIndexVersionCreated().onOrAfter(Version.V_6_1_0)
&& (context.getMapperService().getLuceneFieldType(TEXT_FIELD_NAME).omitNorms() == false)) { && (context.getMapperService().fieldType(TEXT_FIELD_NAME).getTextSearchInfo().hasNorms())) {
assertThat(query, equalTo(new ConstantScoreQuery(new NormsFieldExistsQuery(TEXT_FIELD_NAME)))); assertThat(query, equalTo(new ConstantScoreQuery(new NormsFieldExistsQuery(TEXT_FIELD_NAME))));
} else { } else {
assertThat(query, equalTo(new ConstantScoreQuery(new TermQuery(new Term("_field_names", TEXT_FIELD_NAME))))); assertThat(query, equalTo(new ConstantScoreQuery(new TermQuery(new Term("_field_names", TEXT_FIELD_NAME)))));
@ -1057,7 +1057,7 @@ public class QueryStringQueryBuilderTests extends AbstractQueryTestCase<QueryStr
queryBuilder = new QueryStringQueryBuilder("_exists_:" + value); queryBuilder = new QueryStringQueryBuilder("_exists_:" + value);
query = queryBuilder.toQuery(context); query = queryBuilder.toQuery(context);
if (context.getIndexSettings().getIndexVersionCreated().onOrAfter(Version.V_6_1_0) if (context.getIndexSettings().getIndexVersionCreated().onOrAfter(Version.V_6_1_0)
&& (context.getMapperService().getLuceneFieldType(TEXT_FIELD_NAME).omitNorms() == false)) { && (context.getMapperService().fieldType(TEXT_FIELD_NAME).getTextSearchInfo().hasNorms())) {
assertThat(query, equalTo(new ConstantScoreQuery(new NormsFieldExistsQuery(TEXT_FIELD_NAME)))); assertThat(query, equalTo(new ConstantScoreQuery(new NormsFieldExistsQuery(TEXT_FIELD_NAME))));
} else { } else {
assertThat(query, equalTo(new ConstantScoreQuery(new TermQuery(new Term("_field_names", TEXT_FIELD_NAME))))); assertThat(query, equalTo(new ConstantScoreQuery(new TermQuery(new Term("_field_names", TEXT_FIELD_NAME)))));

View File

@ -141,8 +141,7 @@ public class RangeQueryBuilderTests extends AbstractQueryTestCase<RangeQueryBuil
&& context.getMapperService().fieldType(queryBuilder.fieldName()).hasDocValues()) { && context.getMapperService().fieldType(queryBuilder.fieldName()).hasDocValues()) {
expectedQuery = new ConstantScoreQuery(new DocValuesFieldExistsQuery(expectedFieldName)); expectedQuery = new ConstantScoreQuery(new DocValuesFieldExistsQuery(expectedFieldName));
} else if (context.getIndexSettings().getIndexVersionCreated().onOrAfter(Version.V_6_1_0) && } else if (context.getIndexSettings().getIndexVersionCreated().onOrAfter(Version.V_6_1_0) &&
context.getMapperService().getLuceneFieldType(queryBuilder.fieldName()) != null && context.getMapperService().fieldType(queryBuilder.fieldName()).getTextSearchInfo().hasNorms()) {
context.getMapperService().getLuceneFieldType(queryBuilder.fieldName()).omitNorms() == false) {
expectedQuery = new ConstantScoreQuery(new NormsFieldExistsQuery(expectedFieldName)); expectedQuery = new ConstantScoreQuery(new NormsFieldExistsQuery(expectedFieldName));
} else { } else {
expectedQuery = new ConstantScoreQuery(new TermQuery(new Term(FieldNamesFieldMapper.NAME, expectedFieldName))); expectedQuery = new ConstantScoreQuery(new TermQuery(new Term(FieldNamesFieldMapper.NAME, expectedFieldName)));

View File

@ -33,6 +33,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.KeywordFieldMapper; import org.elasticsearch.index.mapper.KeywordFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.NumberFieldMapper; import org.elasticsearch.index.mapper.NumberFieldMapper;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.InnerHitBuilder; import org.elasticsearch.index.query.InnerHitBuilder;
import org.elasticsearch.index.query.InnerHitBuilderTests; import org.elasticsearch.index.query.InnerHitBuilderTests;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
@ -196,7 +197,7 @@ public class CollapseBuilderTests extends AbstractSerializingTestCase<CollapseBu
} }
{ {
MappedFieldType fieldType = new MappedFieldType("field", true, true, Collections.emptyMap()) { MappedFieldType fieldType = new MappedFieldType("field", true, true, TextSearchInfo.NONE, Collections.emptyMap()) {
@Override @Override
public MappedFieldType clone() { public MappedFieldType clone() {
return null; return null;

View File

@ -18,8 +18,8 @@
*/ */
package org.elasticsearch.search.fetch.subphase.highlight; package org.elasticsearch.search.fetch.subphase.highlight;
import org.apache.lucene.document.FieldType;
import org.elasticsearch.common.text.Text; import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.mapper.MappedFieldType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -64,7 +64,7 @@ public class CustomHighlighter implements Highlighter {
} }
@Override @Override
public boolean canHighlight(FieldType fieldType) { public boolean canHighlight(MappedFieldType fieldType) {
return true; return true;
} }

View File

@ -52,6 +52,7 @@ import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.fielddata.IndexNumericFieldData;
import org.elasticsearch.index.mapper.IdFieldMapper; import org.elasticsearch.index.mapper.IdFieldMapper;
import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.search.internal.ShardSearchRequest; import org.elasticsearch.search.internal.ShardSearchRequest;
@ -118,7 +119,7 @@ public class SliceBuilderTests extends ESTestCase {
private QueryShardContext createShardContext(Version indexVersionCreated, IndexReader reader, private QueryShardContext createShardContext(Version indexVersionCreated, IndexReader reader,
String fieldName, DocValuesType dvType, int numShards, int shardId) { String fieldName, DocValuesType dvType, int numShards, int shardId) {
MappedFieldType fieldType = new MappedFieldType(fieldName, true, dvType != null, Collections.emptyMap()) { MappedFieldType fieldType = new MappedFieldType(fieldName, true, dvType != null, TextSearchInfo.NONE, Collections.emptyMap()) {
@Override @Override
public MappedFieldType clone() { public MappedFieldType clone() {
return null; return null;

View File

@ -49,7 +49,7 @@ public class MockFieldMapper extends FieldMapper {
public static class FakeFieldType extends TermBasedFieldType { public static class FakeFieldType extends TermBasedFieldType {
public FakeFieldType(String name) { public FakeFieldType(String name) {
super(name, true, false, Collections.emptyMap()); super(name, true, false, TextSearchInfo.SIMPLE_MATCH_ONLY, Collections.emptyMap());
} }
protected FakeFieldType(FakeFieldType ref) { protected FakeFieldType(FakeFieldType ref) {

View File

@ -44,6 +44,7 @@ import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.mapper.TypeParsers; import org.elasticsearch.index.mapper.TypeParsers;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.QueryShardException; import org.elasticsearch.index.query.QueryShardException;
@ -163,7 +164,7 @@ public class HistogramFieldMapper extends FieldMapper {
public static class HistogramFieldType extends MappedFieldType { public static class HistogramFieldType extends MappedFieldType {
public HistogramFieldType(String name, boolean hasDocValues, Map<String, String> meta) { public HistogramFieldType(String name, boolean hasDocValues, Map<String, String> meta) {
super(name, false, hasDocValues, meta); super(name, false, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
} }
HistogramFieldType(HistogramFieldType ref) { HistogramFieldType(HistogramFieldType ref) {

View File

@ -47,6 +47,7 @@ import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.StringFieldType; import org.elasticsearch.index.mapper.StringFieldType;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.indices.breaker.CircuitBreakerService; import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.DocValueFormat;
@ -231,7 +232,7 @@ public final class FlatObjectFieldMapper extends DynamicKeyFieldMapper {
public KeyedFlatObjectFieldType(String name, boolean indexed, boolean hasDocValues, String key, public KeyedFlatObjectFieldType(String name, boolean indexed, boolean hasDocValues, String key,
boolean splitQueriesOnWhitespace, Map<String, String> meta) { boolean splitQueriesOnWhitespace, Map<String, String> meta) {
super(name, indexed, hasDocValues, meta); super(name, indexed, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
if (splitQueriesOnWhitespace == false) { if (splitQueriesOnWhitespace == false) {
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
@ -482,7 +483,7 @@ public final class FlatObjectFieldMapper extends DynamicKeyFieldMapper {
public RootFlatObjectFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta, public RootFlatObjectFieldType(String name, boolean indexed, boolean hasDocValues, Map<String, String> meta,
boolean splitQueriesOnWhitespace) { boolean splitQueriesOnWhitespace) {
super(name, indexed, hasDocValues, meta); super(name, indexed, hasDocValues, TextSearchInfo.SIMPLE_MATCH_ONLY, meta);
this.splitQueriesOnWhitespace = splitQueriesOnWhitespace; this.splitQueriesOnWhitespace = splitQueriesOnWhitespace;
setIndexAnalyzer(Lucene.KEYWORD_ANALYZER); setIndexAnalyzer(Lucene.KEYWORD_ANALYZER);
if (splitQueriesOnWhitespace) { if (splitQueriesOnWhitespace) {

View File

@ -24,6 +24,7 @@ import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
@ -99,7 +100,7 @@ public class DenseVectorFieldMapper extends FieldMapper {
private final int dims; private final int dims;
public DenseVectorFieldType(String name, int dims, Map<String, String> meta) { public DenseVectorFieldType(String name, int dims, Map<String, String> meta) {
super(name, false, false, meta); super(name, false, false, TextSearchInfo.NONE, meta);
this.dims = dims; this.dims = dims;
} }

View File

@ -24,6 +24,7 @@ import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.Mapper;
import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.DocValueFormat; import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType; import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
@ -86,7 +87,7 @@ public class SparseVectorFieldMapper extends FieldMapper {
public static final class SparseVectorFieldType extends MappedFieldType { public static final class SparseVectorFieldType extends MappedFieldType {
public SparseVectorFieldType(String name, Map<String, String> meta) { public SparseVectorFieldType(String name, Map<String, String> meta) {
super(name, false, false, meta); super(name, false, false, TextSearchInfo.NONE, meta);
} }
protected SparseVectorFieldType(SparseVectorFieldType ref) { protected SparseVectorFieldType(SparseVectorFieldType ref) {

View File

@ -61,6 +61,7 @@ import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.ParseContext; import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.ParseContext.Document; import org.elasticsearch.index.mapper.ParseContext.Document;
import org.elasticsearch.index.mapper.TextSearchInfo;
import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.similarity.SimilarityProvider; import org.elasticsearch.index.similarity.SimilarityProvider;
import org.elasticsearch.indices.breaker.CircuitBreakerService; import org.elasticsearch.indices.breaker.CircuitBreakerService;
@ -175,7 +176,7 @@ public class WildcardFieldMapper extends FieldMapper {
@Override @Override
public WildcardFieldMapper build(BuilderContext context) { public WildcardFieldMapper build(BuilderContext context) {
return new WildcardFieldMapper( return new WildcardFieldMapper(
name, fieldType, new WildcardFieldType(buildFullName(context), meta), ignoreAbove, name, fieldType, new WildcardFieldType(buildFullName(context), fieldType, meta), ignoreAbove,
multiFieldsBuilder.build(this, context), copyTo, nullValue); multiFieldsBuilder.build(this, context), copyTo, nullValue);
} }
} }
@ -215,8 +216,8 @@ public class WildcardFieldMapper extends FieldMapper {
static Analyzer lowercaseNormalizer = new LowercaseNormalizer(); static Analyzer lowercaseNormalizer = new LowercaseNormalizer();
public WildcardFieldType(String name, Map<String, String> meta) { public WildcardFieldType(String name, FieldType fieldType, Map<String, String> meta) {
super(name, true, true, meta); super(name, true, true, new TextSearchInfo(fieldType), meta);
setIndexAnalyzer(WILDCARD_ANALYZER); setIndexAnalyzer(WILDCARD_ANALYZER);
setSearchAnalyzer(Lucene.KEYWORD_ANALYZER); setSearchAnalyzer(Lucene.KEYWORD_ANALYZER);
} }

View File

@ -16,6 +16,6 @@ public class WildcardFieldTypeTests extends FieldTypeTestCase<MappedFieldType> {
@Override @Override
protected MappedFieldType createDefaultFieldType(String name, Map<String, String> meta) { protected MappedFieldType createDefaultFieldType(String name, Map<String, String> meta) {
return new WildcardFieldMapper.WildcardFieldType(name, meta); return new WildcardFieldMapper.WildcardFieldType(name, WildcardFieldMapper.Defaults.FIELD_TYPE, meta);
} }
} }