Skip to content

Commit

Permalink
Adapt field limit deprecation warning (#35302)
Browse files Browse the repository at this point in the history
With #35284 changing the limit on the amount of fields that a query can be
expanded to to be determined by the `indices.query.bool.max_clause_count`
setting, the changes the deprecation warning and docs in 6.x accordingly.

Relates to #35284
  • Loading branch information
Christoph Büscher authored Nov 8, 2018
1 parent ffcd5fb commit 85a3ade
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 40 deletions.
5 changes: 3 additions & 2 deletions docs/reference/migration/migrate_6_6.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ See also <<release-highlights>> and <<es-release-notes>>.

Using automatically expanded fields for the "all fields" mode ("default_field": "*")
for the `query_string`, `multi_match` and `simple_query_string` now raises a warning and
a deprecation notice to be logged for queries beyond 1024 fields. This limit will be
enforced with a hard error starting in 7.0.
a deprecation notice to be logged for queries beyond a certain number of fields. This limit
will be enforced with a hard error starting in 7.0 and is determined by the
`indices.query.bool.max_clause_count` setting which defaults to 1024.

[float]
==== Deprecate `_source_exclude` and `_source_include` URL Parameters
Expand Down
7 changes: 4 additions & 3 deletions docs/reference/query-dsl/multi-match-query.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,10 @@ index settings, which in turn defaults to `*`. `*` extracts all fields in the ma
are eligible to term queries and filters the metadata fields. All extracted fields are then
combined to build a query.

WARNING: If you have a huge number of fields, the above auto expansion might lead to
querying a large number of fields which might cause performance issues. In future versions
(stating in 7.0) there will be a limit of no more than 1024 fields that can be queried at once.
WARNING: If you have a huge number of fields, the above auto expansion might lead to querying a
large number of fields which might cause performance issues. In future versions (starting in 7.0),
there will be a limit on the number of fields that can be queried at once. This limit will be
determined by the `indices.query.bool.max_clause_count` setting which defaults to 1024.

[[multi-match-types]]
[float]
Expand Down
6 changes: 3 additions & 3 deletions docs/reference/query-dsl/query-string-query.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ settings, which in turn defaults to `*`.
and filters the metadata fields. All extracted fields are then combined
to build a query when no prefix field is provided.

WARNING The amount of fields being allowed to be queries at once will be limited
to 1024 in the next major version or Elasticsearch. Currently this will be raised
and logged as a Warning only.
WARNING: In future versions (starting in 7.0), there will be a limit on the number of fields that can
be queried at once. This limit will be determined by the `indices.query.bool.max_clause_count`
setting which defaults to 1024. Currently this will be raised and logged as a Warning only.

|`default_operator` |The default operator used if no explicit operator
is specified. For example, with a default operator of `OR`, the query
Expand Down
6 changes: 3 additions & 3 deletions docs/reference/query-dsl/simple-query-string-query.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ The `simple_query_string` top level parameters include:
`*` extracts all fields in the mapping that are eligible to term queries
and filters the metadata fields.

WARNING The amount of fields being allowed to be queries at once will be limited
to 1024 in the next major version or Elasticsearch. Currently this will be raised
and logged as a Warning only.
WARNING: In future versions (starting in 7.0), there will be a limit on the number of fields that can
be queried at once. This limit will be determined by the `indices.query.bool.max_clause_count`
setting which defaults to 1024. Currently this will be raised and logged as a Warning only.

|`default_operator` |The default operator used if no explicit operator
is specified. For example, with a default operator of `OR`, the query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.index.query.QueryShardException;
import org.elasticsearch.search.SearchModule;

import java.util.Collection;
import java.util.HashMap;
Expand Down Expand Up @@ -65,7 +66,7 @@ public static Map<String, Float> parseFieldsAndWeights(List<String> fields) {
}

public static Map<String, Float> resolveMappingFields(QueryShardContext context,
Map<String, Float> fieldsAndWeights) {
Map<String, Float> fieldsAndWeights) {
return resolveMappingFields(context, fieldsAndWeights, null);
}

Expand All @@ -79,18 +80,18 @@ public static Map<String, Float> resolveMappingFields(QueryShardContext context,
* in the mapping.
*/
public static Map<String, Float> resolveMappingFields(QueryShardContext context,
Map<String, Float> fieldsAndWeights,
String fieldSuffix) {
Map<String, Float> fieldsAndWeights,
String fieldSuffix) {
Map<String, Float> resolvedFields = new HashMap<>();
for (Map.Entry<String, Float> fieldEntry : fieldsAndWeights.entrySet()) {
boolean allField = Regex.isMatchAllPattern(fieldEntry.getKey());
boolean multiField = Regex.isSimpleMatchPattern(fieldEntry.getKey());
float weight = fieldEntry.getValue() == null ? 1.0f : fieldEntry.getValue();
Map<String, Float> fieldMap = resolveMappingField(context, fieldEntry.getKey(), weight,
!multiField, !allField, fieldSuffix);
!multiField, !allField, fieldSuffix);
resolvedFields.putAll(fieldMap);
}
checkForTooManyFields(resolvedFields);
checkForTooManyFields(resolvedFields, context);
return resolvedFields;
}

Expand All @@ -105,7 +106,7 @@ public static Map<String, Float> resolveMappingFields(QueryShardContext context,
* @param acceptMetadataField Whether metadata fields should be added when a pattern is expanded.
*/
public static Map<String, Float> resolveMappingField(QueryShardContext context, String fieldOrPattern, float weight,
boolean acceptAllTypes, boolean acceptMetadataField) {
boolean acceptAllTypes, boolean acceptMetadataField) {
return resolveMappingField(context, fieldOrPattern, weight, acceptAllTypes, acceptMetadataField, null);
}

Expand All @@ -123,7 +124,7 @@ public static Map<String, Float> resolveMappingField(QueryShardContext context,
* in the mapping.
*/
public static Map<String, Float> resolveMappingField(QueryShardContext context, String fieldOrPattern, float weight,
boolean acceptAllTypes, boolean acceptMetadataField, String fieldSuffix) {
boolean acceptAllTypes, boolean acceptMetadataField, String fieldSuffix) {
Collection<String> allFields = context.simpleMatchToIndexNames(fieldOrPattern);
Map<String, Float> fields = new HashMap<>();
for (String fieldName : allFields) {
Expand Down Expand Up @@ -155,16 +156,18 @@ public static Map<String, Float> resolveMappingField(QueryShardContext context,
}
fields.put(fieldName, weight);
}
checkForTooManyFields(fields);
checkForTooManyFields(fields, context);
return fields;
}

private static void checkForTooManyFields(Map<String, Float> fields) {
if (fields.size() > 1024) {
private static void checkForTooManyFields(Map<String, Float> fields, QueryShardContext context) {
Integer limit = SearchModule.INDICES_MAX_CLAUSE_COUNT_SETTING.get(context.getIndexSettings().getSettings());
if (fields.size() > limit) {
DEPRECATION_LOGGER.deprecatedAndMaybeLog("field_expansion_limit",
"Field expansion matches too many fields, got: {}. A limit of 1024 will be enforced starting "
+ "with version 7.0 of Elasticsearch. Lowering the number of fields will be necessary before upgrading.",
fields.size());
"Field expansion matches too many fields, got: {}. This will be limited starting with version 7.0 of Elasticsearch. " +
"The limit will be detemined by the `indices.query.bool.max_clause_count` setting which is currently set to {}. " +
"You should look at lowering the maximum number of fields targeted by a query or increase the above limit " +
"while being aware that this can negatively affect your clusters performance.", fields.size(), limit);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.elasticsearch.index.IndexService;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.query.QueryShardContext;
import org.elasticsearch.search.SearchModule;
import org.elasticsearch.test.ESSingleNodeTestCase;

import java.util.Collections;
Expand All @@ -32,36 +33,56 @@

public class QueryParserHelperTests extends ESSingleNodeTestCase {

private Integer maxClauseCountSetting;

@Override
public void setUp() throws Exception {
this.maxClauseCountSetting = randomIntBetween(50, 100);
super.setUp();
}

/**
* Test that when {@link QueryParserHelper#resolveMappingFields(QueryShardContext, java.util.Map, String)} exceeds
* the limit of 1024 fields, we emit a warning
* Test that when
* {@link QueryParserHelper#resolveMappingFields(QueryShardContext, java.util.Map, String)}
* exceeds the limit defined by
* {@link SearchModule#INDICES_MAX_CLAUSE_COUNT_SETTING}.
*/
public void testLimitOnExpandedFields() throws Exception {

XContentBuilder builder = jsonBuilder();
builder.startObject();
builder.startObject("type1");
builder.startObject("_doc");
builder.startObject("properties");
for (int i = 0; i < 1025; i++) {
for (int i = 0; i < maxClauseCountSetting + 1; i++) {
builder.startObject("field" + i).field("type", "text").endObject();
}
builder.endObject(); // properties
builder.endObject(); // type1
builder.endObject();
IndexService indexService = createIndex("toomanyfields", Settings.builder()
.put(MapperService.INDEX_MAPPING_TOTAL_FIELDS_LIMIT_SETTING.getKey(), 1200).build(),
"type1", builder);
client().prepareIndex("toomanyfields", "type1", "1").setSource("field171", "foo bar baz").get();
IndexService indexService = createIndex(
"toomanyfields", Settings.builder()
.put(MapperService.INDEX_MAPPING_TOTAL_FIELDS_LIMIT_SETTING.getKey(), maxClauseCountSetting + 100).build(),
"_doc", builder);
client().prepareIndex("toomanyfields", "_doc", "1").setSource("field1", "foo bar baz").get();

QueryShardContext queryShardContext = indexService.newQueryShardContext(
randomInt(20), null, () -> { throw new UnsupportedOperationException(); }, null);
QueryShardContext queryShardContext = indexService.newQueryShardContext(randomInt(20), null, () -> {
throw new UnsupportedOperationException();
}, null);

final String expectedWarning = "Field expansion matches too many fields, got: "+ (maxClauseCountSetting + 1) +". "
+ "This will be limited starting with version 7.0 of Elasticsearch. The limit will be detemined by the "
+ "`indices.query.bool.max_clause_count` setting which is currently set to " + maxClauseCountSetting + ". "
+ "You should look at lowering the maximum number of fields targeted by a query or increase the above limit "
+ "while being aware that this can negatively affect your clusters performance.";

QueryParserHelper.resolveMappingField(queryShardContext, "*", 1.0f, true, false);
assertWarnings("Field expansion matches too many fields, got: 1025. A limit of 1024 will be enforced starting with "
+ "version 7.0 of Elasticsearch. Lowering the number of fields will be necessary before upgrading.");
assertWarnings(expectedWarning);

QueryParserHelper.resolveMappingFields(queryShardContext, Collections.singletonMap("*", 1.0f));
assertWarnings(expectedWarning);
}

QueryParserHelper.resolveMappingFields(queryShardContext,Collections.singletonMap("*", 1.0f));
assertWarnings("Field expansion matches too many fields, got: 1025. A limit of 1024 will be enforced starting with "
+ "version 7.0 of Elasticsearch. Lowering the number of fields will be necessary before upgrading.");
@Override
protected Settings nodeSettings() {
return Settings.builder().put(SearchModule.INDICES_MAX_CLAUSE_COUNT_SETTING.getKey(), this.maxClauseCountSetting).build();
}
}

0 comments on commit 85a3ade

Please sign in to comment.