Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions src/main/java/org/elasticsearch/index/mapper/DocumentMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,18 @@ public static class Builder {

private final Settings indexSettings;

private final MapperService mapperService;

private final RootObjectMapper rootObjectMapper;

private ImmutableMap<String, Object> meta = ImmutableMap.of();

private final Mapper.BuilderContext builderContext;

public Builder(String index, Settings indexSettings, RootObjectMapper.Builder builder) {
public Builder(String index, Settings indexSettings, MapperService mapperService, RootObjectMapper.Builder builder) {
this.index = index;
this.indexSettings = indexSettings;
this.mapperService = mapperService;
this.builderContext = new Mapper.BuilderContext(indexSettings, new ContentPath(1));
this.rootObjectMapper = builder.build(builderContext);
IdFieldMapper idFieldMapper = new IdFieldMapper();
Expand Down Expand Up @@ -245,7 +248,7 @@ public Builder transform(ScriptService scriptService, String script, ScriptType

public DocumentMapper build(DocumentMapperParser docMapperParser) {
Preconditions.checkNotNull(rootObjectMapper, "Mapper builder must have the root object mapper set");
return new DocumentMapper(index, indexSettings, docMapperParser, rootObjectMapper, meta,
return new DocumentMapper(index, indexSettings, mapperService, docMapperParser, rootObjectMapper, meta,
indexAnalyzer, searchAnalyzer, searchQuoteAnalyzer, rootMappers, sourceTransforms);
}
}
Expand All @@ -264,6 +267,8 @@ protected ParseContext.InternalParseContext initialValue() {

private final Settings indexSettings;

private final MapperService mapperService;

private final String type;
private final StringAndBytesText typeText;

Expand Down Expand Up @@ -300,13 +305,14 @@ protected ParseContext.InternalParseContext initialValue() {

private final List<SourceTransform> sourceTransforms;

public DocumentMapper(String index, @Nullable Settings indexSettings, DocumentMapperParser docMapperParser,
public DocumentMapper(String index, @Nullable Settings indexSettings, MapperService mapperService, DocumentMapperParser docMapperParser,
RootObjectMapper rootObjectMapper,
ImmutableMap<String, Object> meta,
NamedAnalyzer indexAnalyzer, NamedAnalyzer searchAnalyzer, NamedAnalyzer searchQuoteAnalyzer,
Map<Class<? extends RootMapper>, RootMapper> rootMappers, List<SourceTransform> sourceTransforms) {
this.index = index;
this.indexSettings = indexSettings;
this.mapperService = mapperService;
this.type = rootObjectMapper.name();
this.typeText = new StringAndBytesText(this.type);
this.docMapperParser = docMapperParser;
Expand Down Expand Up @@ -481,6 +487,10 @@ public ImmutableMap<String, ObjectMapper> objectMappers() {
return this.objectMappers;
}

public MapperService mapperService() {
return this.mapperService;
}

public ParsedDocument parse(BytesReference source) throws MapperParsingException {
return parse(SourceToParse.source(source));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public class DocumentMapperParser extends AbstractIndexComponent {
private final DocValuesFormatService docValuesFormatService;
private final SimilarityLookupService similarityLookupService;
private final ScriptService scriptService;
private final MapperService mapperService;

private final RootObjectMapper.TypeParser rootObjectTypeParser = new RootObjectMapper.TypeParser();

Expand All @@ -76,7 +77,7 @@ public class DocumentMapperParser extends AbstractIndexComponent {
private volatile ImmutableMap<String, Mapper.TypeParser> typeParsers;
private volatile ImmutableMap<String, Mapper.TypeParser> rootTypeParsers;

public DocumentMapperParser(Index index, @IndexSettings Settings indexSettings, AnalysisService analysisService,
public DocumentMapperParser(Index index, @IndexSettings Settings indexSettings, MapperService mapperService, AnalysisService analysisService,
PostingsFormatService postingsFormatService, DocValuesFormatService docValuesFormatService,
SimilarityLookupService similarityLookupService, ScriptService scriptService) {
super(index, indexSettings);
Expand All @@ -85,6 +86,7 @@ public DocumentMapperParser(Index index, @IndexSettings Settings indexSettings,
this.docValuesFormatService = docValuesFormatService;
this.similarityLookupService = similarityLookupService;
this.scriptService = scriptService;
this.mapperService = mapperService;
MapBuilder<String, Mapper.TypeParser> typeParsersBuilder = new MapBuilder<String, Mapper.TypeParser>()
.put(ByteFieldMapper.CONTENT_TYPE, new ByteFieldMapper.TypeParser())
.put(ShortFieldMapper.CONTENT_TYPE, new ShortFieldMapper.TypeParser())
Expand Down Expand Up @@ -208,7 +210,7 @@ private DocumentMapper parse(String type, Map<String, Object> mapping, String de

Mapper.TypeParser.ParserContext parserContext = parserContext();
// parse RootObjectMapper
DocumentMapper.Builder docBuilder = doc(index.name(), indexSettings, (RootObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext));
DocumentMapper.Builder docBuilder = doc(index.name(), indexSettings, mapperService, (RootObjectMapper.Builder) rootObjectTypeParser.parse(type, mapping, parserContext));
Iterator<Map.Entry<String, Object>> iterator = mapping.entrySet().iterator();
// parse DocumentMapper
while(iterator.hasNext()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ private MapperBuilders() {

}

public static DocumentMapper.Builder doc(String index, Settings settings, RootObjectMapper.Builder objectBuilder) {
return new DocumentMapper.Builder(index, settings, objectBuilder);
public static DocumentMapper.Builder doc(String index, Settings settings, MapperService mapperService, RootObjectMapper.Builder objectBuilder) {
return new DocumentMapper.Builder(index, settings, mapperService, objectBuilder);
}

public static SourceFieldMapper.Builder source() {
Expand Down
40 changes: 38 additions & 2 deletions src/main/java/org/elasticsearch/index/mapper/MapperService.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.elasticsearch.common.compress.CompressedString;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.lucene.search.AndFilter;
import org.elasticsearch.common.lucene.search.NotFilter;
import org.elasticsearch.common.lucene.search.XBooleanFilter;
Expand All @@ -58,6 +59,7 @@
import org.elasticsearch.index.mapper.object.ObjectMapper;
import org.elasticsearch.index.search.nested.NonNestedDocsFilter;
import org.elasticsearch.index.settings.IndexSettings;
import org.elasticsearch.index.settings.IndexSettingsService;
import org.elasticsearch.index.similarity.SimilarityLookupService;
import org.elasticsearch.indices.InvalidTypeNameException;
import org.elasticsearch.indices.TypeMissingException;
Expand Down Expand Up @@ -119,15 +121,37 @@ public class MapperService extends AbstractIndexComponent {

private volatile ImmutableMap<String, FieldMapper<?>> unmappedFieldMappers = ImmutableMap.of();

public static final String SETTING_SUBFIELDS_LIMIT = "index.subfields.limit";
public static final String SETTING_SUBFIELDS_DYNAMIC_AT_LIMIT = "index.subfields.dynamic_at_limit";

private final IndexSettingsService indexSettingsService;

private final ApplySettings applySettings = new ApplySettings();

private int subfieldsLimit;
private String subfieldsDynamicAtLimit;

class ApplySettings implements IndexSettingsService.Listener {
@Override
public void onRefreshSettings(Settings settings) {
subfieldsLimit = settings.getAsInt(SETTING_SUBFIELDS_LIMIT, 0);
subfieldsDynamicAtLimit = settings.get(SETTING_SUBFIELDS_DYNAMIC_AT_LIMIT, "strict");
}
}

@Inject
public MapperService(Index index, @IndexSettings Settings indexSettings, Environment environment, AnalysisService analysisService, IndexFieldDataService fieldDataService,
public MapperService(Index index, @IndexSettings Settings indexSettings, IndexSettingsService indexSettingsService, Environment environment, AnalysisService analysisService, IndexFieldDataService fieldDataService,
PostingsFormatService postingsFormatService, DocValuesFormatService docValuesFormatService, SimilarityLookupService similarityLookupService,
ScriptService scriptService) {
super(index, indexSettings);
this.indexSettingsService = indexSettingsService;
subfieldsLimit = indexSettings.getAsInt(SETTING_SUBFIELDS_LIMIT, 0);
subfieldsDynamicAtLimit = indexSettings.get(SETTING_SUBFIELDS_DYNAMIC_AT_LIMIT, "strict");
this.indexSettingsService.addListener(applySettings);
this.analysisService = analysisService;
this.fieldDataService = fieldDataService;
this.fieldMappers = new FieldMappersLookup();
this.documentParser = new DocumentMapperParser(index, indexSettings, analysisService, postingsFormatService, docValuesFormatService, similarityLookupService, scriptService);
this.documentParser = new DocumentMapperParser(index, indexSettings, this, analysisService, postingsFormatService, docValuesFormatService, similarityLookupService, scriptService);
this.searchAnalyzer = new SmartIndexNameSearchAnalyzer(analysisService.defaultSearchAnalyzer());
this.searchQuoteAnalyzer = new SmartIndexNameSearchQuoteAnalyzer(analysisService.defaultSearchQuoteAnalyzer());

Expand Down Expand Up @@ -244,6 +268,18 @@ public boolean hasNested() {
return this.hasNested;
}

public int subfieldsLimit() {
return this.subfieldsLimit;
}

public String subfieldsDynamicAtLimit() {
return this.subfieldsDynamicAtLimit;
}

public ESLogger logger() {
return logger;
}

/**
* returns an immutable iterator over current document mappers.
*
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/org/elasticsearch/index/mapper/ParseContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,14 @@ public Settings indexSettings() {
return this.indexSettings;
}

public int subfieldsLimit() {
return this.docMapper.mapperService().subfieldsLimit();
}

public String subfieldsDynamicAtLimit() {
return this.docMapper.mapperService().subfieldsDynamicAtLimit();
}

public String type() {
return sourceToParse.type();
}
Expand Down Expand Up @@ -709,6 +717,14 @@ public boolean isWithinMultiFields() {
@Nullable
public abstract Settings indexSettings();

public int subfieldsLimit() {
return 0;
}

public String subfieldsDynamicAtLimit() {
return "strict";
}

public abstract String type();

public abstract SourceToParse sourceToParse();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

import static com.google.common.collect.Lists.newArrayList;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue;
import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeIntegerValue;
import static org.elasticsearch.index.mapper.MapperBuilders.*;
import static org.elasticsearch.index.mapper.core.TypeParsers.parsePathType;

Expand Down Expand Up @@ -563,6 +564,19 @@ private void serializeObject(final ParseContext context, String currentFieldName
// we sync here just so we won't add it twice. Its not the end of the world
// to sync here since next operations will get it before
synchronized (mutex) {
int maxNumberOfFields = context.subfieldsLimit();
if (maxNumberOfFields > 0 && mappers.size() >= maxNumberOfFields) {
String dynamicAtLimit = context.subfieldsDynamicAtLimit();
if (dynamicAtLimit.equalsIgnoreCase("strict")) {
throw new StrictDynamicMappingException(fullPath, currentFieldName);
} else {
context.docMapper().mapperService().logger().warn("[" + currentFieldName +
"] exceeds the max number of fields configured for [" + fullPath + "]");
if (!nodeBooleanValue(dynamicAtLimit)) {
return;
}
}
}
objectMapper = mappers.get(currentFieldName);
if (objectMapper == null) {
// remove the current field name from path, since template search and the object builder add it as well...
Expand Down Expand Up @@ -604,7 +618,6 @@ private void serializeArray(ParseContext context, String lastFieldName) throws I
serializeNonDynamicArray(context, lastFieldName, arrayFieldName);
}
} else {

Dynamic dynamic = this.dynamic;
if (dynamic == null) {
dynamic = context.root().dynamic();
Expand All @@ -615,6 +628,19 @@ private void serializeArray(ParseContext context, String lastFieldName) throws I
// we sync here just so we won't add it twice. Its not the end of the world
// to sync here since next operations will get it before
synchronized (mutex) {
int maxNumberOfFields = context.subfieldsLimit();
if (maxNumberOfFields > 0 && mappers.size() >= maxNumberOfFields) {
String dynamicAtLimit = context.subfieldsDynamicAtLimit();
if (dynamicAtLimit.equalsIgnoreCase("strict")) {
throw new StrictDynamicMappingException(fullPath, arrayFieldName);
} else {
context.docMapper().mapperService().logger().warn("[" + arrayFieldName +
"] exceeds the max number of fields configured for [" + fullPath + "]");
if (!nodeBooleanValue(dynamicAtLimit)) {
return;
}
}
}
mapper = mappers.get(arrayFieldName);
if (mapper == null) {
Mapper.Builder builder = context.root().findTemplateBuilder(context, arrayFieldName, "object");
Expand Down Expand Up @@ -724,6 +750,19 @@ public void parseDynamicValue(final ParseContext context, String currentFieldNam
// its not the end of the world, since we add it to the mappers once we create it
// so next time we won't even get here for this field
synchronized (mutex) {
int maxNumberOfFields = context.subfieldsLimit();
if (maxNumberOfFields > 0 && mappers.size() >= maxNumberOfFields) {
String dynamicAtLimit = context.subfieldsDynamicAtLimit();
if (dynamicAtLimit.equalsIgnoreCase("strict")) {
throw new StrictDynamicMappingException(fullPath, currentFieldName);
} else {
context.docMapper().mapperService().logger().warn("[" + currentFieldName +
"] exceeds the max number of fields configured for [" + fullPath + "]");
if (!nodeBooleanValue(dynamicAtLimit)) {
return;
}
}
}
Mapper mapper = mappers.get(currentFieldName);
if (mapper == null) {
BuilderContext builderContext = new BuilderContext(context.indexSettings(), context.path());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.elasticsearch.gateway.local.LocalGatewayAllocator;
import org.elasticsearch.index.engine.EngineConfig;
import org.elasticsearch.index.indexing.slowlog.ShardSlowLogIndexingService;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.merge.policy.LogByteSizeMergePolicyProvider;
import org.elasticsearch.index.merge.policy.LogDocMergePolicyProvider;
import org.elasticsearch.index.merge.policy.TieredMergePolicyProvider;
Expand Down Expand Up @@ -124,6 +125,8 @@ public IndexDynamicSettingsModule() {
indexDynamicSettings.addDynamicSetting(IndicesWarmer.INDEX_WARMER_ENABLED);
indexDynamicSettings.addDynamicSetting(IndicesQueryCache.INDEX_CACHE_QUERY_ENABLED, Validator.BOOLEAN);
indexDynamicSettings.addDynamicSetting(UnassignedInfo.INDEX_DELAYED_NODE_LEFT_TIMEOUT_SETTING, Validator.TIME);
indexDynamicSettings.addDynamicSetting(MapperService.SETTING_SUBFIELDS_LIMIT, Validator.NON_NEGATIVE_INTEGER);
indexDynamicSettings.addDynamicSetting(MapperService.SETTING_SUBFIELDS_DYNAMIC_AT_LIMIT);
}

public void addDynamicSettings(String... settings) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public void testBuildThenParse() throws Exception {
Settings settings = indexService.settingsService().getSettings();
DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser();

DocumentMapper builderDocMapper = doc("test", settings, rootObject("person").add(
DocumentMapper builderDocMapper = doc("test", settings, indexService.mapperService(), rootObject("person").add(
stringField("name").store(true)
.addMultiField(stringField("indexed").index(true).tokenized(true))
.addMultiField(stringField("not_indexed").index(false).store(true))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void testSimpleMapper() throws Exception {
IndexService indexService = createIndex("test");
Settings settings = indexService.settingsService().getSettings();
DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser();
DocumentMapper docMapper = doc("test", settings,
DocumentMapper docMapper = doc("test", settings, indexService.mapperService(),
rootObject("person")
.add(object("name").add(stringField("first").store(true).index(false)))
).build(mapperParser);
Expand Down Expand Up @@ -124,7 +124,7 @@ public void testNoDocumentSent() throws Exception {
IndexService indexService = createIndex("test");
Settings settings = indexService.settingsService().getSettings();
DocumentMapperParser mapperParser = indexService.mapperService().documentMapperParser();
DocumentMapper docMapper = doc("test", settings,
DocumentMapper docMapper = doc("test", settings, indexService.mapperService(),
rootObject("person")
.add(object("name").add(stringField("first").store(true).index(false)))
).build(mapperParser);
Expand Down