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`,
|
The following type parameters are deprecated for the `geo_shape` field type: `tree`,
|
||||||
`precision`, `tree_levels`, `distance_error_pct`, `points_only`, and `strategy`. They
|
`precision`, `tree_levels`, `distance_error_pct`, `points_only`, and `strategy`. They
|
||||||
will be removed in a future version.
|
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;
|
package org.elasticsearch.index.mapper;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.lucene.codecs.PostingsFormat;
|
import org.apache.lucene.codecs.PostingsFormat;
|
||||||
import org.apache.lucene.index.IndexableField;
|
import org.apache.lucene.index.IndexableField;
|
||||||
import org.apache.lucene.index.Term;
|
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.RegexCompletionQuery;
|
||||||
import org.apache.lucene.search.suggest.document.SuggestField;
|
import org.apache.lucene.search.suggest.document.SuggestField;
|
||||||
import org.elasticsearch.Version;
|
import org.elasticsearch.Version;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
import org.elasticsearch.common.ParseField;
|
import org.elasticsearch.common.ParseField;
|
||||||
import org.elasticsearch.common.ParsingException;
|
import org.elasticsearch.common.ParsingException;
|
||||||
|
import org.elasticsearch.common.logging.DeprecationLogger;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.Fuzziness;
|
import org.elasticsearch.common.unit.Fuzziness;
|
||||||
import org.elasticsearch.common.util.set.Sets;
|
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 class CompletionFieldMapper extends FieldMapper implements ArrayValueMapperParser {
|
||||||
public static final String CONTENT_TYPE = "completion";
|
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 class Defaults {
|
||||||
public static final MappedFieldType FIELD_TYPE = new CompletionFieldType();
|
public static final MappedFieldType FIELD_TYPE = new CompletionFieldType();
|
||||||
static {
|
static {
|
||||||
|
@ -354,6 +362,8 @@ public class CompletionFieldMapper extends FieldMapper implements ArrayValueMapp
|
||||||
private boolean preserveSeparators = Defaults.DEFAULT_PRESERVE_SEPARATORS;
|
private boolean preserveSeparators = Defaults.DEFAULT_PRESERVE_SEPARATORS;
|
||||||
private boolean preservePositionIncrements = Defaults.DEFAULT_POSITION_INCREMENTS;
|
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
|
* @param name of the completion field to build
|
||||||
*/
|
*/
|
||||||
|
@ -397,6 +407,7 @@ public class CompletionFieldMapper extends FieldMapper implements ArrayValueMapp
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CompletionFieldMapper build(BuilderContext context) {
|
public CompletionFieldMapper build(BuilderContext context) {
|
||||||
|
checkCompletionContextsLimit(context);
|
||||||
setupFieldType(context);
|
setupFieldType(context);
|
||||||
CompletionFieldType completionFieldType = (CompletionFieldType) this.fieldType;
|
CompletionFieldType completionFieldType = (CompletionFieldType) this.fieldType;
|
||||||
completionFieldType.setContextMappings(contextMappings);
|
completionFieldType.setContextMappings(contextMappings);
|
||||||
|
@ -405,6 +416,15 @@ public class CompletionFieldMapper extends FieldMapper implements ArrayValueMapp
|
||||||
return new CompletionFieldMapper(name, this.fieldType, context.indexSettings(),
|
return new CompletionFieldMapper(name, this.fieldType, context.indexSettings(),
|
||||||
multiFieldsBuilder.build(this, context), copyTo, maxInputLength);
|
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;
|
private int maxInputLength;
|
||||||
|
|
|
@ -54,6 +54,7 @@ import java.util.Map;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
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.arrayContainingInAnyOrder;
|
||||||
import static org.hamcrest.Matchers.arrayWithSize;
|
import static org.hamcrest.Matchers.arrayWithSize;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
@ -908,6 +909,27 @@ public class CompletionFieldMapperTests extends ESSingleNodeTestCase {
|
||||||
assertThat(e.getMessage(), containsString("name cannot be empty string"));
|
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) {
|
private Matcher<IndexableField> suggestField(String value) {
|
||||||
return Matchers.allOf(hasProperty(IndexableField::stringValue, equalTo(value)),
|
return Matchers.allOf(hasProperty(IndexableField::stringValue, equalTo(value)),
|
||||||
Matchers.instanceOf(SuggestField.class));
|
Matchers.instanceOf(SuggestField.class));
|
||||||
|
|
Loading…
Reference in New Issue