Core: Enable doc values by default, when appropriate

Doc values significantly reduced heap usage, which results in faster
GCs. This change makes the default for doc values dynamic: any
field that is indexed but not analyzed now has doc values. This only
affects fields on indexes created with 2.0+.

closes #8312
closes #10209
This commit is contained in:
Ryan Ernst 2015-03-17 16:14:08 -07:00
parent 3f459f69a7
commit e0334dcb9e
38 changed files with 382 additions and 267 deletions

View File

@ -90,7 +90,7 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
public static class Defaults {
public static final FieldType FIELD_TYPE = new FieldType();
public static final boolean DOC_VALUES = false;
public static final boolean PRE_2X_DOC_VALUES = false;
static {
FIELD_TYPE.setTokenized(true);
@ -302,7 +302,7 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
protected FieldDataType fieldDataType;
protected final MultiFields multiFields;
protected CopyTo copyTo;
protected final boolean writePre2xSettings;
protected final boolean indexCreatedBefore2x;
protected AbstractFieldMapper(Names names, float boost, FieldType fieldType, Boolean docValues, NamedAnalyzer indexAnalyzer,
NamedAnalyzer searchAnalyzer, SimilarityProvider similarity,
@ -319,8 +319,10 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
this.boost = boost;
this.fieldType = fieldType;
this.fieldType.freeze();
if (indexAnalyzer == null && this.fieldType.tokenized() == false && this.fieldType.indexOptions() != IndexOptions.NONE) {
this.indexCreatedBefore2x = Version.indexCreated(indexSettings).before(Version.V_2_0_0);
boolean indexedNotAnalyzed = this.fieldType.tokenized() == false && this.fieldType.indexOptions() != IndexOptions.NONE;
if (indexAnalyzer == null && indexedNotAnalyzed) {
this.indexAnalyzer = this.searchAnalyzer = Lucene.KEYWORD_ANALYZER;
} else {
this.indexAnalyzer = indexAnalyzer;
@ -339,16 +341,22 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
ImmutableSettings.builder().put(defaultFieldDataType().getSettings()).put(fieldDataSettings)
);
}
if (docValues != null) {
// explicitly set
this.docValues = docValues;
} else if (fieldDataType == null) {
this.docValues = false;
} else if (fieldDataType != null && FieldDataType.DOC_VALUES_FORMAT_VALUE.equals(fieldDataType.getFormat(indexSettings))) {
// convoluted way to enable doc values, should be removed in the future
this.docValues = true;
} else if (Version.indexCreated(indexSettings).onOrAfter(Version.V_2_0_0)) {
// 2.0+ index, default to true when appropriate
this.docValues = defaultDocValues();
} else {
this.docValues = FieldDataType.DOC_VALUES_FORMAT_VALUE.equals(fieldDataType.getFormat(indexSettings));
}
// old default, disable
this.docValues = false;
}
this.multiFields = multiFields;
this.copyTo = copyTo;
this.writePre2xSettings = Version.indexCreated(indexSettings).before(Version.V_2_0_0);
}
@Nullable
@ -360,6 +368,19 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
protected String defaultDocValuesFormat() {
return null;
}
protected boolean defaultDocValues() {
if (indexCreatedBefore2x) {
return Defaults.PRE_2X_DOC_VALUES;
} else {
return fieldType.tokenized() == false && fieldType.indexOptions() != IndexOptions.NONE;
}
}
@Override
public final boolean hasDocValues() {
return docValues;
}
@Override
public String name() {
@ -683,7 +704,7 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
protected void doXContentBody(XContentBuilder builder, boolean includeDefaults, Params params) throws IOException {
builder.field("type", contentType());
if (writePre2xSettings && (includeDefaults || !names.name().equals(names.indexNameClean()))) {
if (indexCreatedBefore2x && (includeDefaults || !names.name().equals(names.indexNameClean()))) {
builder.field("index_name", names.indexNameClean());
}
@ -701,7 +722,7 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
if (includeDefaults || fieldType.stored() != defaultFieldType.stored()) {
builder.field("store", fieldType.stored());
}
if (includeDefaults || hasDocValues() != Defaults.DOC_VALUES) {
if (includeDefaults || hasDocValues() != defaultDocValues()) {
builder.field(TypeParsers.DOC_VALUES, docValues);
}
if (includeDefaults || fieldType.storeTermVectors() != defaultFieldType.storeTermVectors()) {
@ -824,11 +845,6 @@ public abstract class AbstractFieldMapper<T> implements FieldMapper<T> {
return true;
}
@Override
public boolean hasDocValues() {
return docValues;
}
@Override
public Loading normsLoading(Loading defaultLoading) {
return normsLoading == null ? defaultLoading : normsLoading;

View File

@ -131,7 +131,7 @@ public class BooleanFieldMapper extends AbstractFieldMapper<Boolean> {
protected BooleanFieldMapper(Names names, float boost, FieldType fieldType, Boolean nullValue,
SimilarityProvider similarity, Loading normsLoading,
@Nullable Settings fieldDataSettings, Settings indexSettings, MultiFields multiFields, CopyTo copyTo) {
super(names, boost, fieldType, null, Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER, similarity, normsLoading, fieldDataSettings, indexSettings, multiFields, copyTo);
super(names, boost, fieldType, false, Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER, similarity, normsLoading, fieldDataSettings, indexSettings, multiFields, copyTo);
this.nullValue = nullValue;
}
@ -256,9 +256,4 @@ public class BooleanFieldMapper extends AbstractFieldMapper<Boolean> {
builder.field("null_value", nullValue);
}
}
@Override
public boolean hasDocValues() {
return false;
}
}

View File

@ -240,7 +240,7 @@ public class CompletionFieldMapper extends AbstractFieldMapper<String> {
// with older postings formats such as Elasticsearch090
public CompletionFieldMapper(Names names, NamedAnalyzer indexAnalyzer, NamedAnalyzer searchAnalyzer, PostingsFormat wrappedPostingsFormat, SimilarityProvider similarity, boolean payloads,
boolean preserveSeparators, boolean preservePositionIncrements, int maxInputLength, Settings indexSettings, MultiFields multiFields, CopyTo copyTo, SortedMap<String, ContextMapping> contextMappings) {
super(names, 1.0f, Defaults.FIELD_TYPE, null, indexAnalyzer, searchAnalyzer, similarity, null, null, indexSettings, multiFields, copyTo);
super(names, 1.0f, Defaults.FIELD_TYPE, false, indexAnalyzer, searchAnalyzer, similarity, null, null, indexSettings, multiFields, copyTo);
analyzingSuggestLookupProvider = new AnalyzingCompletionLookupProvider(preserveSeparators, false, preservePositionIncrements, payloads);
if (wrappedPostingsFormat == null) {
// delayed until postingsFormat() is called
@ -494,11 +494,6 @@ public class CompletionFieldMapper extends AbstractFieldMapper<String> {
return false;
}
@Override
public boolean hasDocValues() {
return false;
}
@Override
public boolean supportsNullValue() {
return false;

View File

@ -197,8 +197,8 @@ public class GeoPointFieldMapper extends AbstractFieldMapper<GeoPoint> implement
latMapperBuilder.precisionStep(precisionStep);
lonMapperBuilder.precisionStep(precisionStep);
}
latMapper = (DoubleFieldMapper) latMapperBuilder.includeInAll(false).store(fieldType.stored()).build(context);
lonMapper = (DoubleFieldMapper) lonMapperBuilder.includeInAll(false).store(fieldType.stored()).build(context);
latMapper = (DoubleFieldMapper) latMapperBuilder.includeInAll(false).store(fieldType.stored()).docValues(false).build(context);
lonMapper = (DoubleFieldMapper) lonMapperBuilder.includeInAll(false).store(fieldType.stored()).docValues(false).build(context);
}
StringFieldMapper geohashMapper = null;
if (enableGeoHash) {
@ -470,6 +470,11 @@ public class GeoPointFieldMapper extends AbstractFieldMapper<GeoPoint> implement
public FieldDataType defaultFieldDataType() {
return new FieldDataType("geo_point");
}
@Override
protected boolean defaultDocValues() {
return false;
}
public DoubleFieldMapper latMapper() {
return latMapper;

View File

@ -215,7 +215,7 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper<String> {
public GeoShapeFieldMapper(FieldMapper.Names names, SpatialPrefixTree tree, String defaultStrategyName, double distanceErrorPct,
Orientation shapeOrientation, FieldType fieldType, Settings indexSettings, MultiFields multiFields, CopyTo copyTo) {
super(names, 1, fieldType, null, null, null, null, null, null, indexSettings, multiFields, copyTo);
super(names, 1, fieldType, false, null, null, null, null, null, indexSettings, multiFields, copyTo);
this.recursiveStrategy = new RecursivePrefixTreeStrategy(tree, names.indexName());
this.recursiveStrategy.setDistErrPct(distanceErrorPct);
this.termStrategy = new TermQueryPrefixTreeStrategy(tree, names.indexName());
@ -234,11 +234,6 @@ public class GeoShapeFieldMapper extends AbstractFieldMapper<String> {
return null;
}
@Override
public boolean hasDocValues() {
return false;
}
@Override
public void parse(ParseContext context) throws IOException {
try {

View File

@ -26,6 +26,7 @@ import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
@ -34,6 +35,7 @@ import org.elasticsearch.common.lucene.all.AllField;
import org.elasticsearch.common.lucene.all.AllTermQuery;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.loader.SettingsLoader;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.fielddata.FieldDataType;
@ -55,6 +57,7 @@ import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeMapValue;
import static org.elasticsearch.index.mapper.MapperBuilders.all;
import static org.elasticsearch.index.mapper.core.TypeParsers.parseField;
@ -125,6 +128,24 @@ public class AllFieldMapper extends AbstractFieldMapper<String> implements Inter
@Override
public Mapper.Builder parse(String name, Map<String, Object> node, ParserContext parserContext) throws MapperParsingException {
AllFieldMapper.Builder builder = all();
// parseField below will happily parse the doc_values setting, but it is then never passed to
// the AllFieldMapper ctor in the builder since it is not valid. Here we validate
// the doc values settings (old and new) are rejected
Object docValues = node.get("doc_values");
if (docValues != null && nodeBooleanValue(docValues)) {
throw new MapperParsingException("Field [" + name + "] is always tokenized and cannot have doc values");
}
// convoluted way of specifying doc values
Object fielddata = node.get("fielddata");
if (fielddata != null) {
Map<String, Object> fielddataMap = nodeMapValue(fielddata, "fielddata");
Object format = fielddataMap.get("format");
if ("doc_values".equals(format)) {
throw new MapperParsingException("Field [" + name + "] is always tokenized and cannot have doc values");
}
}
parseField(builder, builder.name, node, parserContext);
for (Iterator<Map.Entry<String, Object>> iterator = node.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String, Object> entry = iterator.next();
@ -158,11 +179,8 @@ public class AllFieldMapper extends AbstractFieldMapper<String> implements Inter
protected AllFieldMapper(String name, FieldType fieldType, NamedAnalyzer indexAnalyzer, NamedAnalyzer searchAnalyzer,
EnabledAttributeMapper enabled, boolean autoBoost, SimilarityProvider similarity, Loading normsLoading,
@Nullable Settings fieldDataSettings, Settings indexSettings) {
super(new Names(name, name, name, name), 1.0f, fieldType, null, indexAnalyzer, searchAnalyzer,
super(new Names(name, name, name, name), 1.0f, fieldType, false, indexAnalyzer, searchAnalyzer,
similarity, normsLoading, fieldDataSettings, indexSettings);
if (hasDocValues()) {
throw new MapperParsingException("Field [" + names.fullName() + "] is always tokenized and cannot have doc values");
}
this.enabledState = enabled;
this.autoBoost = autoBoost;

View File

@ -268,7 +268,7 @@ public class FieldNamesFieldMapper extends AbstractFieldMapper<String> implement
if (includeDefaults || enabledState != Defaults.ENABLED_STATE) {
builder.field("enabled", enabledState.enabled);
}
if (writePre2xSettings && (includeDefaults || fieldType().equals(Defaults.FIELD_TYPE) == false)) {
if (indexCreatedBefore2x && (includeDefaults || fieldType().equals(Defaults.FIELD_TYPE) == false)) {
super.doXContentBody(builder, includeDefaults, params);
}

View File

@ -349,7 +349,7 @@ public class IdFieldMapper extends AbstractFieldMapper<String> implements Intern
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
if (writePre2xSettings == false) {
if (indexCreatedBefore2x == false) {
return builder;
}
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);

View File

@ -27,7 +27,6 @@ import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.fielddata.FieldDataType;
@ -90,7 +89,7 @@ public class IndexFieldMapper extends AbstractFieldMapper<String> implements Int
@Override
public IndexFieldMapper build(BuilderContext context) {
return new IndexFieldMapper(name, indexName, boost, fieldType, docValues, enabledState, fieldDataSettings, context.indexSettings());
return new IndexFieldMapper(name, indexName, boost, fieldType, enabledState, fieldDataSettings, context.indexSettings());
}
}
@ -119,12 +118,12 @@ public class IndexFieldMapper extends AbstractFieldMapper<String> implements Int
private EnabledAttributeMapper enabledState;
public IndexFieldMapper(Settings indexSettings) {
this(Defaults.NAME, Defaults.NAME, Defaults.BOOST, new FieldType(Defaults.FIELD_TYPE), null, Defaults.ENABLED_STATE, null, indexSettings);
this(Defaults.NAME, Defaults.NAME, Defaults.BOOST, new FieldType(Defaults.FIELD_TYPE), Defaults.ENABLED_STATE, null, indexSettings);
}
public IndexFieldMapper(String name, String indexName, float boost, FieldType fieldType, Boolean docValues, EnabledAttributeMapper enabledState,
public IndexFieldMapper(String name, String indexName, float boost, FieldType fieldType, EnabledAttributeMapper enabledState,
@Nullable Settings fieldDataSettings, Settings indexSettings) {
super(new Names(name, indexName, indexName, name), boost, fieldType, docValues, Lucene.KEYWORD_ANALYZER,
super(new Names(name, indexName, indexName, name), boost, fieldType, false, Lucene.KEYWORD_ANALYZER,
Lucene.KEYWORD_ANALYZER, null, null, fieldDataSettings, indexSettings);
this.enabledState = enabledState;
}
@ -143,11 +142,6 @@ public class IndexFieldMapper extends AbstractFieldMapper<String> implements Int
return new FieldDataType(IndexFieldMapper.NAME);
}
@Override
public boolean hasDocValues() {
return false;
}
public String value(Document document) {
Field field = (Field) document.getField(names.indexName());
return field == null ? null : value(field);
@ -203,14 +197,14 @@ public class IndexFieldMapper extends AbstractFieldMapper<String> implements Int
return builder;
}
builder.startObject(CONTENT_TYPE);
if (writePre2xSettings && (includeDefaults || fieldType().stored() != Defaults.FIELD_TYPE.stored())) {
if (indexCreatedBefore2x && (includeDefaults || fieldType().stored() != Defaults.FIELD_TYPE.stored())) {
builder.field("store", fieldType().stored());
}
if (includeDefaults || enabledState != Defaults.ENABLED_STATE) {
builder.field("enabled", enabledState.enabled);
}
if (writePre2xSettings) {
if (indexCreatedBefore2x) {
if (customFieldDataSettings != null) {
builder.field("fielddata", (Map) customFieldDataSettings.getAsMap());
} else if (includeDefaults) {

View File

@ -151,7 +151,7 @@ public class ParentFieldMapper extends AbstractFieldMapper<Uid> implements Inter
private final BytesRef typeAsBytes;
protected ParentFieldMapper(String name, String indexName, String type, @Nullable Settings fieldDataSettings, Settings indexSettings) {
super(new Names(name, indexName, indexName, name), Defaults.BOOST, new FieldType(Defaults.FIELD_TYPE), null,
super(new Names(name, indexName, indexName, name), Defaults.BOOST, new FieldType(Defaults.FIELD_TYPE), false,
Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER, null, null, fieldDataSettings, indexSettings);
this.type = type;
this.typeAsBytes = type == null ? null : new BytesRef(type);
@ -176,11 +176,6 @@ public class ParentFieldMapper extends AbstractFieldMapper<Uid> implements Inter
return new FieldDataType("_parent", settingsBuilder().put(Loading.KEY, Loading.EAGER_VALUE));
}
@Override
public boolean hasDocValues() {
return false;
}
@Override
public void preParse(ParseContext context) throws IOException {
}

View File

@ -131,7 +131,7 @@ public class RoutingFieldMapper extends AbstractFieldMapper<String> implements I
}
protected RoutingFieldMapper(FieldType fieldType, boolean required, String path, @Nullable Settings fieldDataSettings, Settings indexSettings) {
super(new Names(Defaults.NAME, Defaults.NAME, Defaults.NAME, Defaults.NAME), 1.0f, fieldType, null, Lucene.KEYWORD_ANALYZER,
super(new Names(Defaults.NAME, Defaults.NAME, Defaults.NAME, Defaults.NAME), 1.0f, fieldType, false, Lucene.KEYWORD_ANALYZER,
Lucene.KEYWORD_ANALYZER, null, null, fieldDataSettings, indexSettings);
this.required = required;
this.path = path;
@ -147,11 +147,6 @@ public class RoutingFieldMapper extends AbstractFieldMapper<String> implements I
return new FieldDataType("string");
}
@Override
public boolean hasDocValues() {
return false;
}
public void markAsRequired() {
this.required = true;
}
@ -229,16 +224,16 @@ public class RoutingFieldMapper extends AbstractFieldMapper<String> implements I
return builder;
}
builder.startObject(CONTENT_TYPE);
if (writePre2xSettings && (includeDefaults || indexed != indexedDefault)) {
if (indexCreatedBefore2x && (includeDefaults || indexed != indexedDefault)) {
builder.field("index", indexTokenizeOptionToString(indexed, fieldType.tokenized()));
}
if (writePre2xSettings && (includeDefaults || fieldType.stored() != Defaults.FIELD_TYPE.stored())) {
if (indexCreatedBefore2x && (includeDefaults || fieldType.stored() != Defaults.FIELD_TYPE.stored())) {
builder.field("store", fieldType.stored());
}
if (includeDefaults || required != Defaults.REQUIRED) {
builder.field("required", required);
}
if (writePre2xSettings && (includeDefaults || path != Defaults.PATH)) {
if (indexCreatedBefore2x && (includeDefaults || path != Defaults.PATH)) {
builder.field("path", path);
}
builder.endObject();

View File

@ -108,17 +108,12 @@ public class SizeFieldMapper extends IntegerFieldMapper implements RootMapper {
}
public SizeFieldMapper(EnabledAttributeMapper enabled, FieldType fieldType, @Nullable Settings fieldDataSettings, Settings indexSettings) {
super(new Names(Defaults.NAME), Defaults.PRECISION_STEP_32_BIT, Defaults.BOOST, fieldType, null, Defaults.NULL_VALUE,
super(new Names(Defaults.NAME), Defaults.PRECISION_STEP_32_BIT, Defaults.BOOST, fieldType, false, Defaults.NULL_VALUE,
Defaults.IGNORE_MALFORMED, Defaults.COERCE, null, null, fieldDataSettings,
indexSettings, MultiFields.empty(), null);
this.enabledState = enabled;
}
@Override
public boolean hasDocValues() {
return false;
}
@Override
protected String contentType() {
return Defaults.NAME;
@ -164,14 +159,14 @@ public class SizeFieldMapper extends IntegerFieldMapper implements RootMapper {
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);
// all are defaults, no need to write it at all
if (!includeDefaults && enabledState == Defaults.ENABLED_STATE && (writePre2xSettings == false || fieldType().stored() == false)) {
if (!includeDefaults && enabledState == Defaults.ENABLED_STATE && (indexCreatedBefore2x == false || fieldType().stored() == false)) {
return builder;
}
builder.startObject(contentType());
if (includeDefaults || enabledState != Defaults.ENABLED_STATE) {
builder.field("enabled", enabledState.enabled);
}
if (writePre2xSettings && (includeDefaults || fieldType().stored() == true)) {
if (indexCreatedBefore2x && (includeDefaults || fieldType().stored() == true)) {
builder.field("store", fieldType().stored());
}
builder.endObject();

View File

@ -207,7 +207,7 @@ public class SourceFieldMapper extends AbstractFieldMapper<byte[]> implements In
protected SourceFieldMapper(String name, boolean enabled, String format, Boolean compress, long compressThreshold,
String[] includes, String[] excludes, Settings indexSettings) {
super(new Names(name, name, name, name), Defaults.BOOST, new FieldType(Defaults.FIELD_TYPE), null,
super(new Names(name, name, name, name), Defaults.BOOST, new FieldType(Defaults.FIELD_TYPE), false,
Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER, null, null, null, indexSettings); // Only stored.
this.enabled = enabled;
this.compress = compress;
@ -241,11 +241,6 @@ public class SourceFieldMapper extends AbstractFieldMapper<byte[]> implements In
return null;
}
@Override
public boolean hasDocValues() {
return false;
}
@Override
public void preParse(ParseContext context) throws IOException {
super.parse(context);

View File

@ -132,7 +132,7 @@ public class TTLFieldMapper extends LongFieldMapper implements InternalMapper, R
protected TTLFieldMapper(FieldType fieldType, EnabledAttributeMapper enabled, long defaultTTL, Explicit<Boolean> ignoreMalformed,
Explicit<Boolean> coerce, @Nullable Settings fieldDataSettings, Settings indexSettings) {
super(new Names(Defaults.NAME, Defaults.NAME, Defaults.NAME, Defaults.NAME), Defaults.PRECISION_STEP_64_BIT,
Defaults.BOOST, fieldType, null, Defaults.NULL_VALUE, ignoreMalformed, coerce,
Defaults.BOOST, fieldType, false, Defaults.NULL_VALUE, ignoreMalformed, coerce,
null, null, fieldDataSettings, indexSettings, MultiFields.empty(), null);
this.enabledState = enabled;
this.defaultTTL = defaultTTL;
@ -146,11 +146,6 @@ public class TTLFieldMapper extends LongFieldMapper implements InternalMapper, R
return this.defaultTTL;
}
@Override
public boolean hasDocValues() {
return false;
}
// Overrides valueForSearch to display live value of remaining ttl
@Override
public Object valueForSearch(Object value) {

View File

@ -230,6 +230,11 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap
return defaultFieldType;
}
@Override
public boolean defaultDocValues() {
return false;
}
public boolean enabled() {
return this.enabledState.enabled;
}
@ -310,7 +315,7 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap
fieldType.stored() == Defaults.FIELD_TYPE.stored() && enabledState == Defaults.ENABLED && path == Defaults.PATH
&& dateTimeFormatter.format().equals(Defaults.DATE_TIME_FORMATTER.format())
&& Defaults.DEFAULT_TIMESTAMP.equals(defaultTimestamp)
&& Defaults.DOC_VALUES == hasDocValues()) {
&& defaultDocValues() == hasDocValues()) {
return builder;
}
builder.startObject(CONTENT_TYPE);
@ -323,7 +328,7 @@ public class TimestampFieldMapper extends DateFieldMapper implements InternalMap
if (includeDefaults || fieldType.stored() != Defaults.FIELD_TYPE.stored()) {
builder.field("store", fieldType.stored());
}
if (includeDefaults || hasDocValues() != Defaults.DOC_VALUES) {
if (includeDefaults || hasDocValues() != defaultDocValues()) {
builder.field(TypeParsers.DOC_VALUES, docValues);
}
if (includeDefaults || path != Defaults.PATH) {

View File

@ -34,7 +34,6 @@ import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.fielddata.FieldDataType;
@ -109,7 +108,7 @@ public class TypeFieldMapper extends AbstractFieldMapper<String> implements Inte
}
public TypeFieldMapper(String name, String indexName, float boost, FieldType fieldType, @Nullable Settings fieldDataSettings, Settings indexSettings) {
super(new Names(name, indexName, indexName, name), boost, fieldType, null, Lucene.KEYWORD_ANALYZER,
super(new Names(name, indexName, indexName, name), boost, fieldType, false, Lucene.KEYWORD_ANALYZER,
Lucene.KEYWORD_ANALYZER, null, null, fieldDataSettings, indexSettings);
}
@ -123,11 +122,6 @@ public class TypeFieldMapper extends AbstractFieldMapper<String> implements Inte
return new FieldDataType("string");
}
@Override
public boolean hasDocValues() {
return false;
}
@Override
public String value(Object value) {
if (value == null) {
@ -191,7 +185,7 @@ public class TypeFieldMapper extends AbstractFieldMapper<String> implements Inte
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
if (writePre2xSettings == false) {
if (indexCreatedBefore2x == false) {
return builder;
}
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);

View File

@ -108,9 +108,16 @@ public class UidFieldMapper extends AbstractFieldMapper<Uid> implements Internal
}
protected UidFieldMapper(String name, String indexName, Boolean docValues, @Nullable Settings fieldDataSettings, Settings indexSettings) {
super(new Names(name, indexName, indexName, name), Defaults.BOOST, new FieldType(Defaults.FIELD_TYPE), docValues,
super(new Names(name, indexName, indexName, name), Defaults.BOOST, new FieldType(Defaults.FIELD_TYPE), docValuesEnabled(docValues, indexSettings),
Lucene.KEYWORD_ANALYZER, Lucene.KEYWORD_ANALYZER, null, null, fieldDataSettings, indexSettings);
}
static Boolean docValuesEnabled(Boolean docValues, Settings indexSettings) {
if (Version.indexCreated(indexSettings).onOrAfter(Version.V_2_0_0)) {
return false; // explicitly disable doc values for 2.0+, for now
}
return docValues;
}
@Override
public FieldType defaultFieldType() {
@ -202,7 +209,7 @@ public class UidFieldMapper extends AbstractFieldMapper<Uid> implements Internal
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
if (writePre2xSettings == false) {
if (indexCreatedBefore2x == false) {
return builder;
}
boolean includeDefaults = params.paramAsBoolean("include_defaults", false);

View File

@ -96,7 +96,7 @@ public class VersionFieldMapper extends AbstractFieldMapper<Long> implements Int
};
public VersionFieldMapper(Settings indexSettings) {
super(new Names(NAME, NAME, NAME, NAME), Defaults.BOOST, Defaults.FIELD_TYPE, null, null, null, null, null, null, indexSettings);
super(new Names(NAME, NAME, NAME, NAME), Defaults.BOOST, Defaults.FIELD_TYPE, true, null, null, null, null, null, indexSettings);
}
@Override
@ -170,9 +170,4 @@ public class VersionFieldMapper extends AbstractFieldMapper<Long> implements Int
public void close() {
fieldCache.remove();
}
@Override
public boolean hasDocValues() {
return true;
}
}

View File

@ -61,32 +61,36 @@ public abstract class AbstractFieldDataTests extends ElasticsearchSingleNodeTest
}
public <IFD extends IndexFieldData<?>> IFD getForField(String fieldName) {
return getForField(getFieldDataType(), fieldName);
return getForField(getFieldDataType(), fieldName, hasDocValues());
}
public <IFD extends IndexFieldData<?>> IFD getForField(FieldDataType type, String fieldName) {
return getForField(type, fieldName, hasDocValues());
}
public <IFD extends IndexFieldData<?>> IFD getForField(FieldDataType type, String fieldName, boolean docValues) {
final FieldMapper<?> mapper;
final BuilderContext context = new BuilderContext(indexService.settingsService().getSettings(), new ContentPath(1));
if (type.getType().equals("string")) {
mapper = MapperBuilders.stringField(fieldName).tokenized(false).fieldDataSettings(type.getSettings()).build(context);
mapper = MapperBuilders.stringField(fieldName).tokenized(false).docValues(docValues).fieldDataSettings(type.getSettings()).build(context);
} else if (type.getType().equals("float")) {
mapper = MapperBuilders.floatField(fieldName).fieldDataSettings(type.getSettings()).build(context);
mapper = MapperBuilders.floatField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context);
} else if (type.getType().equals("double")) {
mapper = MapperBuilders.doubleField(fieldName).fieldDataSettings(type.getSettings()).build(context);
mapper = MapperBuilders.doubleField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context);
} else if (type.getType().equals("long")) {
mapper = MapperBuilders.longField(fieldName).fieldDataSettings(type.getSettings()).build(context);
mapper = MapperBuilders.longField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context);
} else if (type.getType().equals("int")) {
mapper = MapperBuilders.integerField(fieldName).fieldDataSettings(type.getSettings()).build(context);
mapper = MapperBuilders.integerField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context);
} else if (type.getType().equals("short")) {
mapper = MapperBuilders.shortField(fieldName).fieldDataSettings(type.getSettings()).build(context);
mapper = MapperBuilders.shortField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context);
} else if (type.getType().equals("byte")) {
mapper = MapperBuilders.byteField(fieldName).fieldDataSettings(type.getSettings()).build(context);
mapper = MapperBuilders.byteField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context);
} else if (type.getType().equals("geo_point")) {
mapper = MapperBuilders.geoPointField(fieldName).fieldDataSettings(type.getSettings()).build(context);
mapper = MapperBuilders.geoPointField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context);
} else if (type.getType().equals("_parent")) {
mapper = MapperBuilders.parent().type(fieldName).build(context);
} else if (type.getType().equals("binary")) {
mapper = MapperBuilders.binaryField(fieldName).fieldDataSettings(type.getSettings()).build(context);
mapper = MapperBuilders.binaryField(fieldName).docValues(docValues).fieldDataSettings(type.getSettings()).build(context);
} else {
throw new UnsupportedOperationException(type.getType());
}

View File

@ -474,7 +474,7 @@ public abstract class AbstractStringFieldDataTests extends AbstractFieldDataImpl
fillExtendedMvSet();
refreshReader();
FieldDataType fieldDataType = new FieldDataType("string", ImmutableSettings.builder().put("global_values", "fixed"));
IndexOrdinalsFieldData ifd = getForField(fieldDataType, "value");
IndexOrdinalsFieldData ifd = getForField(fieldDataType, "value", hasDocValues());
IndexOrdinalsFieldData globalOrdinals = ifd.loadGlobal(topLevelReader);
assertThat(topLevelReader.leaves().size(), equalTo(3));
@ -601,11 +601,12 @@ public abstract class AbstractStringFieldDataTests extends AbstractFieldDataImpl
fillExtendedMvSet();
refreshReader();
FieldDataType fieldDataType = new FieldDataType("string", ImmutableSettings.builder().put("global_values", "fixed").put("cache", "node"));
IndexOrdinalsFieldData ifd = getForField(fieldDataType, "value");
IndexOrdinalsFieldData ifd = getForField(fieldDataType, "value", hasDocValues());
IndexOrdinalsFieldData globalOrdinals = ifd.loadGlobal(topLevelReader);
assertThat(ifd.loadGlobal(topLevelReader), sameInstance(globalOrdinals));
// 3 b/c 1 segment level caches and 1 top level cache
assertThat(indicesFieldDataCache.getCache().size(), equalTo(4l));
// in case of doc values, we don't cache atomic FD, so only the top-level cache is there
assertThat(indicesFieldDataCache.getCache().size(), equalTo(hasDocValues() ? 1L : 4L));
IndexOrdinalsFieldData cachedInstance = null;
for (Accountable ramUsage : indicesFieldDataCache.getCache().asMap().values()) {
@ -617,7 +618,7 @@ public abstract class AbstractStringFieldDataTests extends AbstractFieldDataImpl
assertThat(cachedInstance, sameInstance(globalOrdinals));
topLevelReader.close();
// Now only 3 segment level entries, only the toplevel reader has been closed, but the segment readers are still used by IW
assertThat(indicesFieldDataCache.getCache().size(), equalTo(3l));
assertThat(indicesFieldDataCache.getCache().size(), equalTo(hasDocValues() ? 0L : 3L));
refreshReader();
assertThat(ifd.loadGlobal(topLevelReader), not(sameInstance(globalOrdinals)));

View File

@ -37,6 +37,11 @@ import static org.hamcrest.Matchers.equalTo;
*/
public class BinaryDVFieldDataTests extends AbstractFieldDataTests {
@Override
protected boolean hasDocValues() {
return true;
}
@Test
public void testDocValue() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("test")

View File

@ -52,7 +52,7 @@ public class IndexFieldDataServiceTests extends ElasticsearchSingleNodeTest {
final IndexFieldDataService ifdService = indexService.fieldData();
for (boolean docValues : Arrays.asList(true, false)) {
final BuilderContext ctx = new BuilderContext(indexService.settingsService().getSettings(), new ContentPath(1));
final StringFieldMapper stringMapper = new StringFieldMapper.Builder("string").tokenized(false).fieldDataSettings(docValues ? DOC_VALUES_SETTINGS : ImmutableSettings.EMPTY).build(ctx);
final StringFieldMapper stringMapper = new StringFieldMapper.Builder("string").tokenized(false).docValues(docValues).build(ctx);
ifdService.clear();
IndexFieldData<?> fd = ifdService.getForField(stringMapper);
if (docValues) {
@ -62,10 +62,10 @@ public class IndexFieldDataServiceTests extends ElasticsearchSingleNodeTest {
}
for (FieldMapper<?> mapper : Arrays.asList(
new ByteFieldMapper.Builder("int").fieldDataSettings(docValues ? DOC_VALUES_SETTINGS : ImmutableSettings.EMPTY).build(ctx),
new ShortFieldMapper.Builder("int").fieldDataSettings(docValues ? DOC_VALUES_SETTINGS : ImmutableSettings.EMPTY).build(ctx),
new IntegerFieldMapper.Builder("int").fieldDataSettings(docValues ? DOC_VALUES_SETTINGS : ImmutableSettings.EMPTY).build(ctx),
new LongFieldMapper.Builder("long").fieldDataSettings(docValues ? DOC_VALUES_SETTINGS : ImmutableSettings.EMPTY).build(ctx)
new ByteFieldMapper.Builder("int").docValues(docValues).build(ctx),
new ShortFieldMapper.Builder("int").docValues(docValues).build(ctx),
new IntegerFieldMapper.Builder("int").docValues(docValues).build(ctx),
new LongFieldMapper.Builder("long").docValues(docValues).build(ctx)
)) {
ifdService.clear();
fd = ifdService.getForField(mapper);
@ -76,7 +76,7 @@ public class IndexFieldDataServiceTests extends ElasticsearchSingleNodeTest {
}
}
final FloatFieldMapper floatMapper = new FloatFieldMapper.Builder("float").fieldDataSettings(docValues ? DOC_VALUES_SETTINGS : ImmutableSettings.EMPTY).build(ctx);
final FloatFieldMapper floatMapper = new FloatFieldMapper.Builder("float").docValues(docValues).build(ctx);
ifdService.clear();
fd = ifdService.getForField(floatMapper);
if (docValues) {
@ -85,7 +85,7 @@ public class IndexFieldDataServiceTests extends ElasticsearchSingleNodeTest {
assertTrue(fd instanceof FloatArrayIndexFieldData);
}
final DoubleFieldMapper doubleMapper = new DoubleFieldMapper.Builder("double").fieldDataSettings(docValues ? DOC_VALUES_SETTINGS : ImmutableSettings.EMPTY).build(ctx);
final DoubleFieldMapper doubleMapper = new DoubleFieldMapper.Builder("double").docValues(docValues).build(ctx);
ifdService.clear();
fd = ifdService.getForField(doubleMapper);
if (docValues) {

View File

@ -29,6 +29,11 @@ public class SortedSetDVStringFieldDataTests extends AbstractStringFieldDataTest
return new FieldDataType("string", ImmutableSettings.builder().put("format", "doc_values").put(OrdinalsBuilder.FORCE_MULTI_ORDINALS, randomBoolean()));
}
@Override
protected boolean hasDocValues() {
return true;
}
@Override
protected long minRamBytesUsed() {
return 0;

View File

@ -1,44 +0,0 @@
/*
* 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.all;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.junit.Test;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.hamcrest.Matchers.containsString;
public class AllMapperOnCusterTests extends ElasticsearchIntegrationTest {
private static final String INDEX = "index";
private static final String TYPE = "type";
@Test
public void test_doc_valuesInvalidMapping() throws Exception {
String mapping = jsonBuilder().startObject().startObject("mappings").startObject(TYPE).startObject("_all").startObject("fielddata").field("format", "doc_values").endObject().endObject().endObject().endObject().endObject().string();
try {
prepareCreate(INDEX).setSource(mapping).get();
fail();
} catch (MapperParsingException e) {
assertThat(e.getDetailedMessage(), containsString("[_all] is always tokenized and cannot have doc values"));
}
}
}

View File

@ -22,6 +22,8 @@ package org.elasticsearch.index.mapper.all;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
@ -29,6 +31,8 @@ import org.elasticsearch.common.lucene.all.AllEntries;
import org.elasticsearch.common.lucene.all.AllField;
import org.elasticsearch.common.lucene.all.AllTermQuery;
import org.elasticsearch.common.lucene.all.AllTokenStream;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
@ -427,4 +431,31 @@ public class SimpleAllMapperTests extends ElasticsearchSingleNodeTest {
mapping += "\"properties\":{}}" ;
createIndex("test").mapperService().documentMapperParser().parse("test", mapping);
}
public void testDocValuesNotAllowed() throws IOException {
String mapping = jsonBuilder().startObject().startObject("type")
.startObject("_all")
.field("doc_values", true)
.endObject().endObject().endObject().string();
try {
createIndex("test").mapperService().documentMapperParser().parse(mapping);
fail();
} catch (MapperParsingException e) {
assertThat(e.getDetailedMessage(), containsString("[_all] is always tokenized and cannot have doc values"));
}
mapping = jsonBuilder().startObject().startObject("type")
.startObject("_all")
.startObject("fielddata")
.field("format", "doc_values")
.endObject().endObject().endObject().endObject().string();
Settings legacySettings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build();
try {
createIndex("test_old", legacySettings).mapperService().documentMapperParser().parse(mapping);
fail();
} catch (MapperParsingException e) {
assertThat(e.getDetailedMessage(), containsString("[_all] is always tokenized and cannot have doc values"));
}
}
}

View File

@ -67,6 +67,7 @@ public class CopyToMapperTests extends ElasticsearchSingleNodeTest {
.startObject("int_to_str_test")
.field("type", "integer")
.field("doc_values", false)
.array("copy_to", "another_field", "new_field")
.endObject()
.endObject().endObject().endObject().string();
@ -111,7 +112,7 @@ public class CopyToMapperTests extends ElasticsearchSingleNodeTest {
assertThat(doc.getFields("int_to_str_test").length, equalTo(1));
assertThat(doc.getFields("int_to_str_test")[0].numericValue().intValue(), equalTo(42));
assertThat(doc.getFields("new_field").length, equalTo(1));
assertThat(doc.getFields("new_field").length, equalTo(2)); // new field has doc values
assertThat(doc.getFields("new_field")[0].numericValue().intValue(), equalTo(42));
fieldMapper = docMapper.mappers().name("new_field").mapper();
@ -234,14 +235,27 @@ public class CopyToMapperTests extends ElasticsearchSingleNodeTest {
XContentBuilder mapping = jsonBuilder().startObject()
.startObject("type")
.startObject("properties")
.startObject("target")
.field("type", "long")
.field("doc_values", false)
.endObject()
.startObject("n1")
.field("type", "nested")
.startObject("properties")
.startObject("target")
.field("type", "long")
.field("doc_values", false)
.endObject()
.startObject("n2")
.field("type", "nested")
.startObject("properties")
.startObject("target")
.field("type", "long")
.field("doc_values", false)
.endObject()
.startObject("source")
.field("type", "long")
.field("doc_values", false)
.startArray("copy_to")
.value("target") // should go to the root doc
.value("n1.target") // should go to the parent doc
@ -250,7 +264,7 @@ public class CopyToMapperTests extends ElasticsearchSingleNodeTest {
.endObject();
for (int i = 0; i < 3; ++i) {
if (mapped) {
mapping = mapping.startObject("target").field("type", "long").endObject();
mapping = mapping.startObject("target").field("type", "long").field("doc_values", false).endObject();
}
mapping = mapping.endObject().endObject();
}

View File

@ -21,6 +21,7 @@ package org.elasticsearch.index.mapper.date;
import org.apache.lucene.analysis.NumericTokenStream.NumericTermAttribute;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.NumericRangeFilter;
import org.elasticsearch.ElasticsearchIllegalArgumentException;
@ -32,7 +33,12 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.mapper.*;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.DocumentMapperParser;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperParsingException;
import org.elasticsearch.index.mapper.ParseContext;
import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.index.mapper.core.DateFieldMapper;
import org.elasticsearch.index.mapper.core.LongFieldMapper;
import org.elasticsearch.index.mapper.core.StringFieldMapper;
@ -41,17 +47,25 @@ import org.elasticsearch.test.ElasticsearchSingleNodeTest;
import org.elasticsearch.test.TestSearchContext;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.junit.Test;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import static org.elasticsearch.index.mapper.string.SimpleStringMappingTests.docValuesType;
import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilder;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
@Test
public void testAutomaticDateParser() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").endObject()
@ -82,7 +96,6 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
assertThat(fieldMapper, instanceOf(StringFieldMapper.class));
}
@Test
public void testParseLocal() {
assertThat(Locale.GERMAN, equalTo(LocaleUtils.parse("de")));
assertThat(Locale.GERMANY, equalTo(LocaleUtils.parse("de_DE")));
@ -98,7 +111,6 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
assertThat(Locale.ROOT, equalTo(LocaleUtils.parse("ROOT")));
}
@Test
public void testLocale() throws IOException {
String mapping = XContentFactory.jsonBuilder()
.startObject()
@ -169,7 +181,6 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
assertThat(pos, equalTo(values.size()));
}
@Test
public void testTimestampAsDate() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("date_field").field("type", "date").endObject().endObject()
@ -187,7 +198,6 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
assertThat(doc.rootDoc().getField("date_field").tokenStream(defaultMapper.mappers().indexAnalyzer(), null), notNullValue());
}
@Test
public void testDateDetection() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.field("date_detection", false)
@ -203,11 +213,10 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
.endObject()
.bytes());
assertThat(doc.rootDoc().get("date_field"), nullValue());
assertThat(doc.rootDoc().get("date_field"), equalTo("1262304000000"));
assertThat(doc.rootDoc().get("date_field_x"), equalTo("2010-01-01"));
}
@Test
public void testHourFormat() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.field("date_detection", false)
@ -235,9 +244,7 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
assertThat(rangeFilter.getMax(), equalTo(new DateTime(TimeValue.timeValueHours(11).millis()).getMillis()));
assertThat(rangeFilter.getMin(), equalTo(new DateTime(TimeValue.timeValueHours(10).millis()).getMillis()));
}
@Test
public void testDayWithoutYearFormat() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.field("date_detection", false)
@ -265,8 +272,7 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
assertThat(rangeFilter.getMax(), equalTo(new DateTime(TimeValue.timeValueHours(35).millis()).getMillis()));
assertThat(rangeFilter.getMin(), equalTo(new DateTime(TimeValue.timeValueHours(34).millis()).getMillis()));
}
@Test
public void testIgnoreMalformedOption() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties")
@ -330,7 +336,6 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
}
}
@Test
public void testThatMergingWorks() throws Exception {
String initialMapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties")
@ -366,6 +371,22 @@ public class SimpleDateMappingTests extends ElasticsearchSingleNodeTest {
Map<String, String> mergedConfig = getConfigurationViaXContent(mergedFieldMapper);
assertThat(mergedConfig.get("format"), is("EEE MMM dd HH:mm:ss.S Z yyyy||EEE MMM dd HH:mm:ss.SSS Z yyyy||yyyy-MM-dd'T'HH:mm:ss.SSSZZ"));
}
public void testDefaultDocValues() throws Exception {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties").startObject("date_field").field("type", "date").endObject().endObject()
.endObject().endObject().string();
DocumentMapper defaultMapper = mapper(mapping);
ParsedDocument parsedDoc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("date_field", "2010-01-01")
.endObject()
.bytes());
ParseContext.Document doc = parsedDoc.rootDoc();
assertEquals(DocValuesType.SORTED_NUMERIC, docValuesType(doc, "date_field"));
}
private Map<String, String> getConfigurationViaXContent(DateFieldMapper dateFieldMapper) throws IOException {
XContentBuilder builder = JsonXContent.contentBuilder().startObject();

View File

@ -55,7 +55,7 @@ public class SimpleIpMappingTests extends ElasticsearchSingleNodeTest {
.bytes());
assertThat(doc.rootDoc().getField("ip").numericValue().longValue(), is(2130706433L));
assertThat(doc.rootDoc().get("ip"), is(nullValue()));
assertThat(doc.rootDoc().get("ip"), is("2130706433"));
}
@Test

View File

@ -20,7 +20,6 @@
package org.elasticsearch.index.mapper.string;
import com.google.common.collect.ImmutableMap;
import org.apache.lucene.index.DocValuesType;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.IndexableField;
@ -28,19 +27,25 @@ import org.apache.lucene.index.IndexableFieldType;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.TermFilter;
import org.apache.lucene.queries.TermsFilter;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.fielddata.FieldDataType;
import org.elasticsearch.index.mapper.*;
import org.elasticsearch.index.mapper.ContentPath;
import org.elasticsearch.index.mapper.DocumentMapper;
import org.elasticsearch.index.mapper.DocumentMapper.MergeFlags;
import org.elasticsearch.index.mapper.DocumentMapper.MergeResult;
import org.elasticsearch.index.mapper.DocumentMapperParser;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.Mapper.BuilderContext;
import org.elasticsearch.index.mapper.ParseContext.Document;
import org.elasticsearch.index.mapper.ParsedDocument;
import org.elasticsearch.index.mapper.core.StringFieldMapper;
import org.elasticsearch.index.IndexService;
import org.elasticsearch.test.ElasticsearchSingleNodeTest;
import org.junit.Before;
import org.junit.Test;
@ -48,7 +53,9 @@ import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
/**
*/
@ -285,34 +292,83 @@ public class SimpleStringMappingTests extends ElasticsearchSingleNodeTest {
assertThat(doc.rootDoc().getField("field6").fieldType().storeTermVectorPayloads(), equalTo(true));
}
public void testDocValues() throws Exception {
// doc values only work on non-analyzed content
public void testDocValuesFielddata() throws Exception {
IndexService indexService = createIndex("index");
DocumentMapperParser parser = indexService.mapperService().documentMapperParser();
final BuilderContext ctx = new BuilderContext(indexService.settingsService().getSettings(), new ContentPath(1));
try {
new StringFieldMapper.Builder("anything").fieldDataSettings(DOC_VALUES_SETTINGS).build(ctx);
fail();
} catch (Exception e) { /* OK */ }
new StringFieldMapper.Builder("anything").tokenized(false).fieldDataSettings(DOC_VALUES_SETTINGS).build(ctx);
new StringFieldMapper.Builder("anything").index(false).fieldDataSettings(DOC_VALUES_SETTINGS).build(ctx);
assertFalse(new StringFieldMapper.Builder("anything").index(false).build(ctx).hasDocValues());
assertTrue(new StringFieldMapper.Builder("anything").index(false).fieldDataSettings(DOC_VALUES_SETTINGS).build(ctx).hasDocValues());
assertTrue(new StringFieldMapper.Builder("anything").index(false).docValues(true).build(ctx).hasDocValues());
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties")
.startObject("str1")
.field("type", "string")
.startObject("fielddata")
.field("format", "fst")
.endObject()
.endObject()
.startObject("str2")
.field("type", "string")
.field("index", "not_analyzed")
.startObject("fielddata")
.field("format", "doc_values")
.endObject()
.endObject()
.endObject()
.endObject().endObject().string();
DocumentMapper defaultMapper = parser.parse(mapping);
ParsedDocument parsedDoc = defaultMapper.parse("type", "1", XContentFactory.jsonBuilder()
.startObject()
.field("str1", "1234")
.field("str2", "1234")
.endObject()
.bytes());
final Document doc = parsedDoc.rootDoc();
assertEquals(DocValuesType.NONE, docValuesType(doc, "str1"));
assertEquals(DocValuesType.SORTED_SET, docValuesType(doc, "str2"));
}
public void testDocValues() throws Exception {
// doc values only work on non-analyzed content
final BuilderContext ctx = new BuilderContext(indexService.settingsService().getSettings(), new ContentPath(1));
try {
new StringFieldMapper.Builder("anything").docValues(true).build(ctx);
fail();
} catch (Exception e) { /* OK */ }
assertFalse(new StringFieldMapper.Builder("anything").index(false).build(ctx).hasDocValues());
assertTrue(new StringFieldMapper.Builder("anything").index(true).tokenized(false).build(ctx).hasDocValues());
assertFalse(new StringFieldMapper.Builder("anything").index(true).tokenized(true).build(ctx).hasDocValues());
assertFalse(new StringFieldMapper.Builder("anything").index(false).tokenized(false).docValues(false).build(ctx).hasDocValues());
assertTrue(new StringFieldMapper.Builder("anything").index(false).docValues(true).build(ctx).hasDocValues());
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("properties")
.startObject("str1")
.field("type", "string")
.startObject("fielddata")
.field("format", "fst")
.endObject()
.field("index", "no")
.endObject()
.startObject("str2")
.field("type", "string")
.field("index", "not_analyzed")
.startObject("fielddata")
.field("format", "doc_values")
.endObject()
.endObject()
.startObject("str3")
.field("type", "string")
.field("index", "analyzed")
.endObject()
.startObject("str4")
.field("type", "string")
.field("index", "not_analyzed")
.field("doc_values", false)
.endObject()
.startObject("str5")
.field("type", "string")
.field("index", "no")
.field("doc_values", true)
.endObject()
.endObject()
.endObject().endObject().string();
@ -323,13 +379,21 @@ public class SimpleStringMappingTests extends ElasticsearchSingleNodeTest {
.startObject()
.field("str1", "1234")
.field("str2", "1234")
.field("str3", "1234")
.field("str4", "1234")
.field("str5", "1234")
.endObject()
.bytes());
final Document doc = parsedDoc.rootDoc();
assertEquals(DocValuesType.NONE, docValuesType(doc, "str1"));
assertEquals(DocValuesType.SORTED_SET, docValuesType(doc, "str2"));
assertEquals(DocValuesType.NONE, docValuesType(doc, "str3"));
assertEquals(DocValuesType.NONE, docValuesType(doc, "str4"));
assertEquals(DocValuesType.SORTED_SET, docValuesType(doc, "str5"));
}
// TODO: this function shouldn't be necessary. parsing should just add a single field that is indexed and dv
public static DocValuesType docValuesType(Document document, String fieldName) {
for (IndexableField field : document.getFields(fieldName)) {
if (field.fieldType().docValuesType() != DocValuesType.NONE) {

View File

@ -33,6 +33,7 @@ import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.joda.Joda;
import org.elasticsearch.common.lucene.Lucene;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
@ -183,6 +184,7 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest {
IndexRequest request = new IndexRequest("test", "type", "1").source(doc);
try {
request.process(metaData, mappingMetaData, true, "test");
fail();
} catch (TimestampParsingException e) {
assertThat(e.getDetailedMessage(), containsString("timestamp is required by mapping"));
}
@ -488,11 +490,12 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest {
String mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("_timestamp").field("enabled", randomBoolean()).startObject("fielddata").field("loading", "lazy").field("format", "doc_values").endObject().field("store", "yes").endObject()
.endObject().endObject().string();
DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser();
Settings indexSettings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build();
DocumentMapperParser parser = createIndex("test", indexSettings).mapperService().documentMapperParser();
DocumentMapper docMapper = parser.parse(mapping);
assertThat(docMapper.timestampFieldMapper().fieldDataType().getLoading(), equalTo(FieldMapper.Loading.LAZY));
assertThat(docMapper.timestampFieldMapper().fieldDataType().getFormat(docMapper.timestampFieldMapper().fieldDataType().getSettings()), equalTo("doc_values"));
assertThat(docMapper.timestampFieldMapper().fieldDataType().getFormat(indexSettings), equalTo("doc_values"));
mapping = XContentFactory.jsonBuilder().startObject().startObject("type")
.startObject("_timestamp").field("enabled", randomBoolean()).startObject("fielddata").field("loading", "eager").field("format", "array").endObject().field("store", "yes").endObject()
.endObject().endObject().string();
@ -500,7 +503,7 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest {
DocumentMapper.MergeResult mergeResult = docMapper.merge(parser.parse(mapping), DocumentMapper.MergeFlags.mergeFlags().simulate(false));
assertThat(mergeResult.conflicts().length, equalTo(0));
assertThat(docMapper.timestampFieldMapper().fieldDataType().getLoading(), equalTo(FieldMapper.Loading.EAGER));
assertThat(docMapper.timestampFieldMapper().fieldDataType().getFormat(docMapper.timestampFieldMapper().fieldDataType().getSettings()), equalTo("array"));
assertThat(docMapper.timestampFieldMapper().fieldDataType().getFormat(indexSettings), equalTo("array"));
}
@Test
@ -558,7 +561,8 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest {
.field("default", "1970-01-01")
.endObject()
.endObject().endObject().string();
DocumentMapperParser parser = createIndex("test").mapperService().documentMapperParser();
Settings indexSettings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build();
DocumentMapperParser parser = createIndex("test", indexSettings).mapperService().documentMapperParser();
DocumentMapper docMapper = parser.parse(mapping);
assertThat(docMapper.timestampFieldMapper().fieldDataType().getLoading(), equalTo(FieldMapper.Loading.LAZY));
@ -581,7 +585,7 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest {
assertThat(mergeResult.conflicts().length, equalTo(expectedConflicts.length));
assertThat(docMapper.timestampFieldMapper().fieldDataType().getLoading(), equalTo(FieldMapper.Loading.LAZY));
assertTrue(docMapper.timestampFieldMapper().enabled());
assertThat(docMapper.timestampFieldMapper().fieldDataType().getFormat(docMapper.timestampFieldMapper().fieldDataType().getSettings()), equalTo("doc_values"));
assertThat(docMapper.timestampFieldMapper().fieldDataType().getFormat(indexSettings), equalTo("doc_values"));
}
@Test
@ -607,7 +611,14 @@ public class TimestampMappingTests extends ElasticsearchSingleNodeTest {
.endObject().endObject().string();
DocumentMapper.MergeResult mergeResult = docMapper.merge(parser.parse(mapping), DocumentMapper.MergeFlags.mergeFlags().simulate(true));
String[] expectedConflicts = {"mapper [_timestamp] has different index values", "mapper [_timestamp] has different tokenize values"};
List<String> expectedConflicts = new ArrayList<>();
expectedConflicts.add("mapper [_timestamp] has different index values");
expectedConflicts.add("mapper [_timestamp] has different tokenize values");
if (indexValues.get(0).equals("not_analyzed") == false) {
// if the only index value left is not_analyzed, then the doc values setting will be the same, but in the
// other two cases, it will change
expectedConflicts.add("mapper [_timestamp] has different doc_values values");
}
for (String conflict : mergeResult.conflicts()) {
assertThat(conflict, isIn(expectedConflicts));

View File

@ -1 +1 @@
{"type":{"_timestamp":{"enabled":false,"doc_values":true,"fielddata":{"format":"doc_values"}},"_index":{"enabled":false},"_size":{"enabled":false},"properties":{}}}
{"type":{"_timestamp":{"enabled":false},"_index":{"enabled":false},"_size":{"enabled":false},"properties":{}}}

View File

@ -81,13 +81,13 @@ public class FieldDataTermsFilterTests extends ElasticsearchSingleNodeTest {
new IndexWriterConfig(new StandardAnalyzer()));
// setup field mappers
strMapper = new StringFieldMapper.Builder("str_value")
strMapper = new StringFieldMapper.Builder("str_value").docValues(false)
.build(new Mapper.BuilderContext(settings, new ContentPath(1)));
lngMapper = new LongFieldMapper.Builder("lng_value")
lngMapper = new LongFieldMapper.Builder("lng_value").docValues(false)
.build(new Mapper.BuilderContext(settings, new ContentPath(1)));
dblMapper = new DoubleFieldMapper.Builder("dbl_value")
dblMapper = new DoubleFieldMapper.Builder("dbl_value").docValues(false)
.build(new Mapper.BuilderContext(settings, new ContentPath(1)));
int numDocs = 10;

View File

@ -61,7 +61,7 @@ public abstract class AbstractChildTests extends ElasticsearchSingleNodeLuceneTe
// Parent/child parsers require that the parent and child type to be presented in mapping
// Sometimes we want a nested object field in the parent type that triggers nonNestedDocsFilter to be used
mapperService.merge(parentType, new CompressedString(PutMappingRequest.buildFromSimplifiedDef(parentType, "nested_field", random().nextBoolean() ? "type=nested" : "type=object").string()), true);
mapperService.merge(childType, new CompressedString(PutMappingRequest.buildFromSimplifiedDef(childType, "_parent", "type=" + parentType, CHILD_SCORE_NAME, "type=double").string()), true);
mapperService.merge(childType, new CompressedString(PutMappingRequest.buildFromSimplifiedDef(childType, "_parent", "type=" + parentType, CHILD_SCORE_NAME, "type=double,doc_values=false").string()), true);
return createSearchContext(indexService);
}

View File

@ -70,6 +70,7 @@ public class RandomExceptionCircuitBreakerTests extends ElasticsearchIntegration
.startObject("test-str")
.field("type", "string")
.field("index", "not_analyzed")
.field("doc_values", randomBoolean())
.startObject("fielddata")
.field("format", randomBytesFieldDataFormat())
.endObject() // fielddata

View File

@ -51,6 +51,7 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
import org.junit.Test;
import java.io.IOException;
@ -187,7 +188,7 @@ public class PercolatorTests extends ElasticsearchIntegrationTest {
@Test
public void testSimple2() throws Exception {
assertAcked(prepareCreate("test").addMapping("type1", "field1", "type=long"));
assertAcked(prepareCreate("test").addMapping("type1", "field1", "type=long,doc_values=true"));
ensureGreen();
// introduce the doc
@ -250,15 +251,19 @@ public class PercolatorTests extends ElasticsearchIntegrationTest {
response = client().preparePercolate()
.setIndices("test").setDocumentType("type1")
.setSource(doc).execute().actionGet();
assertMatchCount(response, 2l);
assertThat(response.getMatches(), arrayWithSize(2));
assertThat(convertFromTextArray(response.getMatches(), "test"), arrayContainingInAnyOrder("test1", "test3"));
ElasticsearchAssertions.assertFailures(response);
// TODO: with doc values by default, fielddata execution mode causes a doc values
// lookup, but memory index doesn't have doc values. we should consider just removing
// execution mode.
//assertMatchCount(response, 2l);
//assertThat(response.getMatches(), arrayWithSize(2));
//assertThat(convertFromTextArray(response.getMatches(), "test"), arrayContainingInAnyOrder("test1", "test3"));
}
@Test
public void testRangeFilterThatUsesFD() throws Exception {
client().admin().indices().prepareCreate("test")
.addMapping("type1", "field1", "type=long")
.addMapping("type1", "field1", "type=long,doc_values=false")
.get();

View File

@ -317,12 +317,13 @@ public abstract class ElasticsearchIntegrationTest extends ElasticsearchTestCase
if (frequently() && randomDynamicTemplates()) {
mappings = XContentFactory.jsonBuilder().startObject().startObject("_default_");
if (randomBoolean()) {
boolean timestampEnabled = randomBoolean();
mappings.startObject(TimestampFieldMapper.NAME)
.field("enabled", randomBoolean())
.startObject("fielddata")
.field(FieldDataType.FORMAT_KEY, randomFrom("array", "doc_values"))
.endObject()
.endObject();
.field("enabled", timestampEnabled);
if (timestampEnabled) {
mappings.field("doc_values", randomBoolean());
}
mappings.endObject();
}
if (randomBoolean()) {
mappings.startObject(SizeFieldMapper.NAME)
@ -332,62 +333,54 @@ public abstract class ElasticsearchIntegrationTest extends ElasticsearchTestCase
if (randomBoolean()) {
mappings.startObject(AllFieldMapper.NAME)
.field("auto_boost", true)
.endObject();
.endObject();
}
if (randomBoolean()) {
mappings.startObject(SourceFieldMapper.NAME)
.field("compress", randomBoolean())
.endObject();
}
if (compatibilityVersion().onOrAfter(Version.V_1_3_0) && compatibilityVersion().before(Version.V_2_0_0)) {
// some tests rely on this BWC version behavior that we wanna keep
mappings.startObject(FieldNamesFieldMapper.NAME)
.startObject("fielddata")
.field(FieldDataType.FORMAT_KEY, randomFrom("paged_bytes", "fst", "doc_values"))
.endObject()
.endObject();
}
mappings.startArray("dynamic_templates")
.startObject()
.startObject("template-strings")
.field("match_mapping_type", "string")
.startObject("template-strings")
.field("match_mapping_type", "string")
.startObject("mapping")
.startObject("fielddata")
.field(FieldDataType.FORMAT_KEY, randomFrom("paged_bytes", "fst")) // unfortunately doc values only work on not_analyzed fields
.field(Loading.KEY, randomLoadingValues())
.startObject("fielddata")
.field(FieldDataType.FORMAT_KEY, randomFrom("paged_bytes", "fst"))
.field(Loading.KEY, randomLoadingValues())
.endObject()
.endObject()
.endObject()
.endObject()
.startObject()
.startObject("template-longs")
.field("match_mapping_type", "long")
.startObject("mapping")
.startObject("fielddata")
.field(FieldDataType.FORMAT_KEY, randomFrom("array", "doc_values"))
.field(Loading.KEY, randomFrom(Loading.LAZY, Loading.EAGER))
.startObject("template-longs")
.field("match_mapping_type", "long")
.startObject("mapping")
.field("doc_values", randomBoolean())
.startObject("fielddata")
.field(Loading.KEY, randomFrom(Loading.LAZY, Loading.EAGER))
.endObject()
.endObject()
.endObject()
.endObject()
.startObject()
.startObject("template-doubles")
.field("match_mapping_type", "double")
.startObject("mapping")
.startObject("fielddata")
.field(FieldDataType.FORMAT_KEY, randomFrom("array", "doc_values"))
.field(Loading.KEY, randomFrom(Loading.LAZY, Loading.EAGER))
.startObject("template-doubles")
.field("match_mapping_type", "double")
.startObject("mapping")
.field("doc_values", randomBoolean())
.startObject("fielddata")
.field(Loading.KEY, randomFrom(Loading.LAZY, Loading.EAGER))
.endObject()
.endObject()
.endObject()
.endObject()
.startObject()
.startObject("template-geo_points")
.field("match_mapping_type", "geo_point")
.startObject("mapping")
.startObject("fielddata")
.field(FieldDataType.FORMAT_KEY, randomFrom("array", "doc_values"))
.field(Loading.KEY, randomFrom(Loading.LAZY, Loading.EAGER))
.startObject("template-geo_points")
.field("match_mapping_type", "geo_point")
.startObject("mapping")
.field("doc_values", randomBoolean())
.startObject("fielddata")
.field(Loading.KEY, randomFrom(Loading.LAZY, Loading.EAGER))
.endObject()
.endObject()
.endObject()
@ -1735,7 +1728,7 @@ public abstract class ElasticsearchIntegrationTest extends ElasticsearchTestCase
* "paged_bytes", "fst", or "doc_values".
*/
public static String randomBytesFieldDataFormat() {
return randomFrom(Arrays.asList("paged_bytes", "fst", "doc_values"));
return randomFrom(Arrays.asList("paged_bytes", "fst"));
}
/**

View File

@ -280,6 +280,12 @@ public class ElasticsearchAssertions {
}
}
public static void assertFailures(PercolateResponse percolateResponse) {
assertThat("Expected at least one shard failure, got none",
percolateResponse.getShardFailures().length, greaterThan(0));
assertVersionSerializable(percolateResponse);
}
public static void assertNoFailures(BroadcastOperationResponse response) {
assertThat("Unexpected ShardFailures: " + Arrays.toString(response.getShardFailures()), response.getFailedShards(), equalTo(0));
assertVersionSerializable(response);

View File

@ -32,7 +32,11 @@ import java.util.Locale;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
import static org.hamcrest.Matchers.notNullValue;
/**
*/