Skip to content

Commit

Permalink
Add deprecation notices for boost mappings to API (#81605)
Browse files Browse the repository at this point in the history
This PR adds checks to the deprecation API that sense when `boost` properties are present 
on mapping fields. The checks examine existing mappings, component templates, and index 
templates, including the mapping data and the dynamic templates.
  • Loading branch information
jbaiera committed Dec 14, 2021
1 parent a29f7f5 commit df63edb
Show file tree
Hide file tree
Showing 5 changed files with 804 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,198 @@ static DeprecationIssue checkComponentTemplatesWithChainedMultiFieldsInDynamicTe
return null;
}

/**
* Check templates that use fields with `boost` values
*/
@SuppressWarnings("unchecked")
static DeprecationIssue checkTemplatesWithBoostedFields(ClusterState state) {
Map<String, List<String>> templatesContainingBoostedFields = new HashMap<>();
state.getMetadata().getTemplates().forEach((templateCursor) -> {
String templateName = templateCursor.key;
templateCursor.value.getMappings().forEach((mappingCursor) -> {
String type = mappingCursor.key;
// There should be the type name at this level, but there was a bug where mappings could be stored without a type (#45120)
// to make sure, we try to detect this like we try to do in MappingMetadata#sourceAsMap()
Map<String, Object> mapping = XContentHelper.convertToMap(mappingCursor.value.compressedReference(), true).v2();
if (mapping.size() == 1 && mapping.containsKey(type)) {
// the type name is the root value, reduce it
mapping = (Map<String, Object>) mapping.get(type);
}
List<String> mappingIssues = IndexDeprecationChecks.findInPropertiesRecursively(
type,
mapping,
IndexDeprecationChecks::containsBoostedFields,
IndexDeprecationChecks::formatField,
"",
""
);
if (mappingIssues.size() > 0) {
templatesContainingBoostedFields.put(templateName, mappingIssues);
}
});
});
if (templatesContainingBoostedFields.isEmpty() == false) {
return new DeprecationIssue(
DeprecationIssue.Level.WARNING,
"Defining boosted fields on index template mappings is deprecated",
"https://ela.st/es-deprecation-7-boost-fields",
String.format(
Locale.ROOT,
"Remove boost fields from the \"%s\" template%s. Configuring a boost value on mapping fields "
+ "is not supported in 8.0.",
String.join(",", templatesContainingBoostedFields.keySet()),
templatesContainingBoostedFields.size() > 1 ? "s" : ""
),
false,
null
);
}
return null;
}

/**
* Check templates that use fields with `boost` values in dynamic templates
*/
@SuppressWarnings("unchecked")
static DeprecationIssue checkTemplatesWithBoostFieldsInDynamicTemplates(ClusterState state) {
Map<String, List<String>> templatesContainingBoostedFields = new HashMap<>();
state.getMetadata().getTemplates().forEach((templateCursor) -> {
String templateName = templateCursor.key;
templateCursor.value.getMappings().forEach((mappingCursor) -> {
String type = mappingCursor.key;
// There should be the type name at this level, but there was a bug where mappings could be stored without a type (#45120)
// to make sure, we try to detect this like we try to do in MappingMetadata#sourceAsMap()
Map<String, Object> mapping = XContentHelper.convertToMap(mappingCursor.value.compressedReference(), true).v2();
if (mapping.size() == 1 && mapping.containsKey(type)) {
// the type name is the root value, reduce it
mapping = (Map<String, Object>) mapping.get(type);
}
List<String> mappingIssues = IndexDeprecationChecks.findInDynamicTemplates(
type,
mapping,
IndexDeprecationChecks::containsMappingWithBoostedFields,
IndexDeprecationChecks::formatField,
"",
""
);
if (mappingIssues.size() > 0) {
templatesContainingBoostedFields.put(templateName, mappingIssues);
}
});
});
if (templatesContainingBoostedFields.isEmpty() == false) {
return new DeprecationIssue(
DeprecationIssue.Level.WARNING,
"Defining boosted fields on index template dynamic_templates is deprecated",
"https://ela.st/es-deprecation-7-boost-fields",
String.format(
Locale.ROOT,
"Remove boost fields from the \"%s\" template%s. Configuring a boost value on mapping fields "
+ "is not supported in 8.0.",
String.join(",", templatesContainingBoostedFields.keySet()),
templatesContainingBoostedFields.size() > 1 ? "s" : ""
),
false,
null
);
}
return null;
}

/**
* Check component templates that use fields with `boost` values
*/
@SuppressWarnings("unchecked")
static DeprecationIssue checkComponentTemplatesWithBoostedFields(ClusterState state) {
Map<String, List<String>> templatesContainingBoostedFields = new HashMap<>();
state.getMetadata().componentTemplates().forEach((templateName, componentTemplate) -> {
CompressedXContent mappings = componentTemplate.template().mappings();
if (mappings != null) {
// Component templates root their mapping data under the "_doc" mapping type. Unpack it if that is the case.
Map<String, Object> mapping = XContentHelper.convertToMap(mappings.compressedReference(), true).v2();
if (mapping.size() == 1 && mapping.containsKey("_doc")) {
// the type name is the root value, reduce it
mapping = (Map<String, Object>) mapping.get("_doc");
}
List<String> mappingIssues = IndexDeprecationChecks.findInPropertiesRecursively(
"_doc",
mapping,
IndexDeprecationChecks::containsBoostedFields,
IndexDeprecationChecks::formatField,
"",
""
);
if (mappingIssues.size() > 0) {
templatesContainingBoostedFields.put(templateName, mappingIssues);
}
}
});
if (templatesContainingBoostedFields.isEmpty() == false) {
return new DeprecationIssue(
DeprecationIssue.Level.WARNING,
"Defining boosted fields on component templates is deprecated",
"https://ela.st/es-deprecation-7-boost-fields",
String.format(
Locale.ROOT,
"Remove boost fields from the \"%s\" component template%s. Configuring a boost value on mapping fields "
+ "is not supported in 8.0.",
String.join(",", templatesContainingBoostedFields.keySet()),
templatesContainingBoostedFields.size() > 1 ? "s" : ""
),
false,
null
);
}
return null;
}

/**
* Check component templates that use fields with `boost` values in dynamic templates
*/
@SuppressWarnings("unchecked")
static DeprecationIssue checkComponentTemplatesWithBoostedFieldsInDynamicTemplates(ClusterState state) {
Map<String, List<String>> templatesContainingBoostedFields = new HashMap<>();
state.getMetadata().componentTemplates().forEach((templateName, componentTemplate) -> {
CompressedXContent mappings = componentTemplate.template().mappings();
if (mappings != null) {
// Component templates root their mapping data under the "_doc" mapping type. Unpack it if that is the case.
Map<String, Object> mapping = XContentHelper.convertToMap(mappings.compressedReference(), true).v2();
if (mapping.size() == 1 && mapping.containsKey("_doc")) {
// the type name is the root value, reduce it
mapping = (Map<String, Object>) mapping.get("_doc");
}
List<String> mappingIssues = IndexDeprecationChecks.findInDynamicTemplates(
"_doc",
mapping,
IndexDeprecationChecks::containsMappingWithBoostedFields,
IndexDeprecationChecks::formatField,
"",
""
);
if (mappingIssues.size() > 0) {
templatesContainingBoostedFields.put(templateName, mappingIssues);
}
}
});
if (templatesContainingBoostedFields.isEmpty() == false) {
return new DeprecationIssue(
DeprecationIssue.Level.WARNING,
"Defining boosted fields on component template dynamic_templates is deprecated",
"https://ela.st/es-deprecation-7-boost-fields",
String.format(
Locale.ROOT,
"Remove boost fields from the \"%s\" component template%s. Configuring a boost value on mapping fields "
+ "is not supported in 8.0.",
String.join(",", templatesContainingBoostedFields.keySet()),
templatesContainingBoostedFields.size() > 1 ? "s" : ""
),
false,
null
);
}
return null;
}

/**
* Check templates that use `_field_names` explicitly, which was deprecated in https://github.com/elastic/elasticsearch/pull/42854
* and will throw an error on new indices in 8.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ private DeprecationChecks() {}
ClusterDeprecationChecks::checkComponentTemplatesWithChainedMultiFields,
ClusterDeprecationChecks::checkTemplatesWithChainedMultiFieldsInDynamicTemplates,
ClusterDeprecationChecks::checkComponentTemplatesWithChainedMultiFieldsInDynamicTemplates,
ClusterDeprecationChecks::checkTemplatesWithBoostedFields,
ClusterDeprecationChecks::checkComponentTemplatesWithBoostedFields,
ClusterDeprecationChecks::checkTemplatesWithBoostFieldsInDynamicTemplates,
ClusterDeprecationChecks::checkComponentTemplatesWithBoostedFieldsInDynamicTemplates,
ClusterDeprecationChecks::checkClusterRoutingAllocationIncludeRelocationsSetting,
ClusterDeprecationChecks::checkGeoShapeTemplates,
ClusterDeprecationChecks::checkSparseVectorTemplates,
Expand Down Expand Up @@ -243,6 +247,8 @@ private static Set<Setting<Boolean>> getAllDeprecatedNodeRolesSettings() {
(clusterState, indexMetadata) -> IndexDeprecationChecks.tooManyFieldsCheck(indexMetadata),
(clusterState, indexMetadata) -> IndexDeprecationChecks.chainedMultiFieldsCheck(indexMetadata),
(clusterState, indexMetadata) -> IndexDeprecationChecks.chainedMultiFieldsDynamicTemplateCheck(indexMetadata),
(clusterState, indexMetadata) -> IndexDeprecationChecks.boostMappingCheck(indexMetadata),
(clusterState, indexMetadata) -> IndexDeprecationChecks.boostDynamicTemplateCheck(indexMetadata),
(clusterState, indexMetadata) -> IndexDeprecationChecks.deprecatedDateTimeFormat(indexMetadata),
(clusterState, indexMetadata) -> IndexDeprecationChecks.translogRetentionSettingCheck(indexMetadata),
(clusterState, indexMetadata) -> IndexDeprecationChecks.fieldNamesDisabledCheck(indexMetadata),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,90 @@ private static boolean isDateFieldWithDeprecatedPattern(Map<?, ?> property) {
&& JodaDeprecationPatterns.isDeprecatedPattern((String) property.get("format"));
}

static DeprecationIssue boostMappingCheck(IndexMetadata indexMetadata) {
List<String> issues = new ArrayList<>();
fieldLevelMappingIssue(
indexMetadata,
((mappingMetadata, sourceAsMap) -> issues.addAll(
findInPropertiesRecursively(
mappingMetadata.type(),
sourceAsMap,
IndexDeprecationChecks::containsBoostedFields,
IndexDeprecationChecks::formatField,
"",
""
)
))
);
if (issues.size() > 0) {
return new DeprecationIssue(
DeprecationIssue.Level.WARNING,
"Configuring boost values in field mappings is deprecated",
"https://ela.st/es-deprecation-7-boost-fields",
String.format(
Locale.ROOT,
"Remove boost fields from the \"%s\" mapping%s. Configuring a boost value on mapping fields "
+ "is not supported in 8.0.",
issues.stream().collect(Collectors.joining(",")),
issues.size() > 1 ? "s" : ""
),
false,
null
);
}
return null;
}

static DeprecationIssue boostDynamicTemplateCheck(IndexMetadata indexMetadata) {
List<String> issues = new ArrayList<>();
fieldLevelMappingIssue(
indexMetadata,
((mappingMetadata, sourceAsMap) -> issues.addAll(
findInDynamicTemplates(
mappingMetadata.type(),
sourceAsMap,
IndexDeprecationChecks::containsMappingWithBoostedFields,
IndexDeprecationChecks::formatField,
"",
""
)
))
);
if (issues.size() > 0) {
return new DeprecationIssue(
DeprecationIssue.Level.WARNING,
"Configuring boost values in field mappings is deprecated",
"https://ela.st/es-deprecation-7-boost-fields",
String.format(
Locale.ROOT,
"Remove boost fields from the \"%s\" dynamic template%s. Configuring a boost value on mapping fields "
+ "is not supported in 8.0.",
issues.stream().collect(Collectors.joining(",")),
issues.size() > 1 ? "s" : ""
),
false,
null
);
}
return null;
}

/**
* Predicate for dynamic templates that contain `boost` fields
* @param property A dynamic mapping template body
*/
static boolean containsMappingWithBoostedFields(Map<?, ?> property) {
if (property.containsKey("mapping")) {
Map<?, ?> mappings = (Map<?, ?>) property.get("mapping");
return containsBoostedFields(mappings);
}
return false;
}

static boolean containsBoostedFields(Map<?, ?> property) {
return property.containsKey("boost");
}

static DeprecationIssue chainedMultiFieldsCheck(IndexMetadata indexMetadata) {
List<String> issues = new ArrayList<>();
fieldLevelMappingIssue(
Expand Down

0 comments on commit df63edb

Please sign in to comment.