Skip to content

Commit 3b827ab

Browse files
committed
Enforce Completion Context Limit
* Enforcing a maximum number of completion contexts as reqested in #32741 * Closes #32741
1 parent 3bf8e24 commit 3b827ab

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

server/src/main/java/org/elasticsearch/index/mapper/MapperService.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ public enum MergeReason {
108108
Setting.boolSetting("index.mapper.dynamic", INDEX_MAPPER_DYNAMIC_DEFAULT,
109109
Property.Dynamic, Property.IndexScope, Property.Deprecated);
110110

111+
// Maximum allowed number of completion contexts in a mapping
112+
public static final int COMPLETION_CONTEXTS_LIMIT = 10;
113+
111114
//TODO this needs to be cleaned up: _timestamp and _ttl are not supported anymore, _field_names, _seq_no, _version and _source are
112115
//also missing, not sure if on purpose. See IndicesModule#getMetadataMappers
113116
private static final String[] SORTED_META_FIELDS = new String[]{
@@ -497,6 +500,7 @@ private synchronized Map<String, DocumentMapper> internalMerge(@Nullable Documen
497500
ContextMapping.validateContextPaths(indexSettings.getIndexVersionCreated(), fieldMappers, fieldTypes::get);
498501

499502
if (reason == MergeReason.MAPPING_UPDATE) {
503+
checkCompletionContextsLimit(fieldMappers);
500504
// this check will only be performed on the master node when there is
501505
// a call to the update mapping API. For all other cases like
502506
// the master node restoring mappings from disk or data nodes
@@ -557,6 +561,18 @@ private synchronized Map<String, DocumentMapper> internalMerge(@Nullable Documen
557561
return results;
558562
}
559563

564+
private void checkCompletionContextsLimit(List<FieldMapper> fieldMappers) {
565+
for (FieldMapper fieldMapper : fieldMappers) {
566+
if (CompletionFieldMapper.CONTENT_TYPE.equals(fieldMapper.typeName())) {
567+
CompletionFieldMapper.CompletionFieldType fieldType = ((CompletionFieldMapper) fieldMapper).fieldType();
568+
if (fieldType.hasContextMappings() && fieldType.getContextMappings().size() > COMPLETION_CONTEXTS_LIMIT) {
569+
throw new IllegalArgumentException("Limit of contexts [" + COMPLETION_CONTEXTS_LIMIT + "] in index ["
570+
+ index().getName() + "] has been exceeded");
571+
}
572+
}
573+
}
574+
}
575+
560576
private boolean assertMappersShareSameFieldType() {
561577
if (mapper != null) {
562578
List<FieldMapper> fieldMappers = new ArrayList<>();

server/src/test/java/org/elasticsearch/index/mapper/MapperServiceTests.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,4 +323,25 @@ public void testDefaultMappingIsRejectedOn7() throws IOException {
323323
+ " that indices can have at most one type.", e.getMessage());
324324
}
325325

326+
public void testLimitOfContextMappings() throws Throwable {
327+
final String index = "test";
328+
XContentBuilder mappingBuilder = XContentFactory.jsonBuilder().startObject().startObject("properties")
329+
.startObject("suggest").field("type", "completion").startArray("contexts");
330+
for (int i = 0; i < MapperService.COMPLETION_CONTEXTS_LIMIT + 1; i++) {
331+
mappingBuilder.startObject();
332+
mappingBuilder.field("name", Integer.toString(i));
333+
mappingBuilder.field("type", "category");
334+
mappingBuilder.endObject();
335+
}
336+
337+
mappingBuilder.endArray().endObject().endObject().endObject();
338+
String mappings = Strings.toString(mappingBuilder);
339+
340+
IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> {
341+
createIndex(index).mapperService().merge("type1", new CompressedXContent(mappings), MergeReason.MAPPING_UPDATE);
342+
});
343+
assertTrue(e.getMessage(),
344+
e.getMessage().contains("Limit of contexts [" + MapperService.COMPLETION_CONTEXTS_LIMIT +
345+
"] in index [" + index + "] has been exceeded"));
346+
}
326347
}

0 commit comments

Comments
 (0)