This change adds a limit to the number of completion contexts that a completion field can define. Closes #32741
This commit is contained in:
parent
59e9a0f4f4
commit
199155f5fb
|
@ -72,3 +72,10 @@ or `quadtree`. This will ensure compatibility with previously created indexes.
|
|||
The following type parameters are deprecated for the `geo_shape` field type: `tree`,
|
||||
`precision`, `tree_levels`, `distance_error_pct`, `points_only`, and `strategy`. They
|
||||
will be removed in a future version.
|
||||
|
||||
[float]
|
||||
==== Limiting the number of completion contexts
|
||||
|
||||
The maximum allowed number of completion contexts in a mapping will be limited
|
||||
to 10 in the next major version. Completion fields that define more than 10
|
||||
contexts in a mapping will log a deprecation warning in this version.
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.lucene.codecs.PostingsFormat;
|
||||
import org.apache.lucene.index.IndexableField;
|
||||
import org.apache.lucene.index.Term;
|
||||
|
@ -31,8 +32,10 @@ import org.apache.lucene.search.suggest.document.PrefixCompletionQuery;
|
|||
import org.apache.lucene.search.suggest.document.RegexCompletionQuery;
|
||||
import org.apache.lucene.search.suggest.document.SuggestField;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.ParsingException;
|
||||
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.Fuzziness;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
|
@ -85,6 +88,11 @@ import static org.elasticsearch.index.mapper.TypeParsers.parseMultiField;
|
|||
public class CompletionFieldMapper extends FieldMapper implements ArrayValueMapperParser {
|
||||
public static final String CONTENT_TYPE = "completion";
|
||||
|
||||
/**
|
||||
* Maximum allowed number of completion contexts in a mapping.
|
||||
*/
|
||||
static final int COMPLETION_CONTEXTS_LIMIT = 10;
|
||||
|
||||
public static class Defaults {
|
||||
public static final MappedFieldType FIELD_TYPE = new CompletionFieldType();
|
||||
static {
|
||||
|
@ -354,6 +362,8 @@ public class CompletionFieldMapper extends FieldMapper implements ArrayValueMapp
|
|||
private boolean preserveSeparators = Defaults.DEFAULT_PRESERVE_SEPARATORS;
|
||||
private boolean preservePositionIncrements = Defaults.DEFAULT_POSITION_INCREMENTS;
|
||||
|
||||
private static final DeprecationLogger deprecationLogger = new DeprecationLogger(LogManager.getLogger(Builder.class));
|
||||
|
||||
/**
|
||||
* @param name of the completion field to build
|
||||
*/
|
||||
|
@ -397,6 +407,7 @@ public class CompletionFieldMapper extends FieldMapper implements ArrayValueMapp
|
|||
|
||||
@Override
|
||||
public CompletionFieldMapper build(BuilderContext context) {
|
||||
checkCompletionContextsLimit(context);
|
||||
setupFieldType(context);
|
||||
CompletionFieldType completionFieldType = (CompletionFieldType) this.fieldType;
|
||||
completionFieldType.setContextMappings(contextMappings);
|
||||
|
@ -405,6 +416,15 @@ public class CompletionFieldMapper extends FieldMapper implements ArrayValueMapp
|
|||
return new CompletionFieldMapper(name, this.fieldType, context.indexSettings(),
|
||||
multiFieldsBuilder.build(this, context), copyTo, maxInputLength);
|
||||
}
|
||||
|
||||
private void checkCompletionContextsLimit(BuilderContext context) {
|
||||
if (this.contextMappings != null && this.contextMappings.size() > COMPLETION_CONTEXTS_LIMIT) {
|
||||
deprecationLogger.deprecated("You have defined more than [" + COMPLETION_CONTEXTS_LIMIT + "] completion contexts" +
|
||||
" in the mapping for index [" + context.indexSettings().get(IndexMetaData.SETTING_INDEX_PROVIDED_NAME) + "]. " +
|
||||
"The maximum allowed number of completion contexts in a mapping will be limited to " +
|
||||
"[" + COMPLETION_CONTEXTS_LIMIT + "] starting in version [8.0].");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int maxInputLength;
|
||||
|
|
|
@ -54,6 +54,7 @@ import java.util.Map;
|
|||
import java.util.function.Function;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.index.mapper.CompletionFieldMapper.COMPLETION_CONTEXTS_LIMIT;
|
||||
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
|
||||
import static org.hamcrest.Matchers.arrayWithSize;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -908,6 +909,27 @@ public class CompletionFieldMapperTests extends ESSingleNodeTestCase {
|
|||
assertThat(e.getMessage(), containsString("name cannot be empty string"));
|
||||
}
|
||||
|
||||
public void testLimitOfContextMappings() throws Throwable {
|
||||
final String index = "test";
|
||||
XContentBuilder mappingBuilder = XContentFactory.jsonBuilder().startObject().startObject("properties")
|
||||
.startObject("suggest").field("type", "completion").startArray("contexts");
|
||||
for (int i = 0; i < COMPLETION_CONTEXTS_LIMIT + 1; i++) {
|
||||
mappingBuilder.startObject();
|
||||
mappingBuilder.field("name", Integer.toString(i));
|
||||
mappingBuilder.field("type", "category");
|
||||
mappingBuilder.endObject();
|
||||
}
|
||||
|
||||
mappingBuilder.endArray().endObject().endObject().endObject();
|
||||
String mappings = Strings.toString(mappingBuilder);
|
||||
|
||||
DocumentMapper mapper = createIndex(index).mapperService().documentMapperParser()
|
||||
.parse("type1", new CompressedXContent(mappings));
|
||||
assertWarnings("You have defined more than [" + COMPLETION_CONTEXTS_LIMIT + "] completion contexts" +
|
||||
" in the mapping for index [test]. The maximum allowed number of completion contexts in a mapping will be limited to " +
|
||||
"[" + COMPLETION_CONTEXTS_LIMIT + "] starting in version [8.0].");
|
||||
}
|
||||
|
||||
private Matcher<IndexableField> suggestField(String value) {
|
||||
return Matchers.allOf(hasProperty(IndexableField::stringValue, equalTo(value)),
|
||||
Matchers.instanceOf(SuggestField.class));
|
||||
|
|
Loading…
Reference in New Issue