Skip to content

Commit 9db2ed8

Browse files
committed
Add other mapping elements
1 parent b71ef9f commit 9db2ed8

File tree

1 file changed

+95
-22
lines changed

1 file changed

+95
-22
lines changed

x-pack/plugin/downsample/src/main/java/org/elasticsearch/xpack/downsample/TransportDownsampleAction.java

Lines changed: 95 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.elasticsearch.cluster.service.MasterServiceTaskQueue;
4646
import org.elasticsearch.common.Priority;
4747
import org.elasticsearch.common.Strings;
48+
import org.elasticsearch.common.TriConsumer;
4849
import org.elasticsearch.common.compress.CompressedXContent;
4950
import org.elasticsearch.common.settings.IndexScopedSettings;
5051
import org.elasticsearch.common.settings.Setting;
@@ -86,6 +87,7 @@
8687
import java.time.OffsetDateTime;
8788
import java.time.format.DateTimeFormatter;
8889
import java.util.ArrayList;
90+
import java.util.HashMap;
8991
import java.util.List;
9092
import java.util.Map;
9193
import java.util.Objects;
@@ -106,7 +108,10 @@
106108
public class TransportDownsampleAction extends AcknowledgedTransportMasterNodeAction<DownsampleAction.Request> {
107109

108110
private static final Logger logger = LogManager.getLogger(TransportDownsampleAction.class);
109-
111+
private static final String MAPPING_PROPERTIES = "properties";
112+
private static final String MAPPING_DYNAMIC_TEMPLATES = "dynamic_templates";
113+
private static final String FIELD_TYPE = "type";
114+
private static final String MULTI_FIELDS = "fields";
110115
private final Client client;
111116
private final IndicesService indicesService;
112117
private final MasterServiceTaskQueue<DownsampleClusterStateUpdateTask> taskQueue;
@@ -677,36 +682,105 @@ static String createDownsampleIndexMapping(
677682
final DownsampleConfig config,
678683
final Map<String, Object> sourceIndexMappings
679684
) throws IOException {
680-
// TODO deep copy the map
681685
final String timestampField = config.getTimestampField();
682686
final String dateIntervalType = config.getIntervalType();
683687
final String dateInterval = config.getInterval().toString();
684688
final String timezone = config.getTimeZone();
685-
addDynamicTemplates(sourceIndexMappings);
686-
MappingVisitor.visitMapping(sourceIndexMappings, (field, mapping) -> {
687-
@SuppressWarnings("unchecked")
688-
Map<String, Object> updatedMapping = (Map<String, Object>) mapping;
689-
if (timestampField.equals(field)) {
690-
final String timestampType = String.valueOf(mapping.get("type"));
691-
updatedMapping.put("type", timestampType != null ? timestampType : DateFieldMapper.CONTENT_TYPE);
689+
Map<String, Object> downsampledMapping = new HashMap<>();
690+
addDynamicTemplateForStrings(downsampledMapping);
691+
for (Map.Entry<String, Object> entry : sourceIndexMappings.entrySet()) {
692+
if (entry.getKey().equals(MAPPING_DYNAMIC_TEMPLATES)) {
693+
List<?> sourceDynamicTemplates = (List<?>) sourceIndexMappings.get(MAPPING_DYNAMIC_TEMPLATES);
694+
@SuppressWarnings("unchecked")
695+
List<Object> downsampledDynamicTemplates = (List<Object>) downsampledMapping.get(MAPPING_DYNAMIC_TEMPLATES);
696+
downsampledDynamicTemplates.addAll(sourceDynamicTemplates);
697+
} else if (entry.getKey().equals(MAPPING_PROPERTIES) == false) {
698+
downsampledMapping.put(entry.getKey(), entry.getValue());
699+
}
700+
}
701+
populateMappingProperties(sourceIndexMappings, downsampledMapping, (fieldName, sourceMapping, updatedMapping) -> {
702+
if (timestampField.equals(fieldName)) {
703+
final String timestampType = String.valueOf(sourceMapping.get(FIELD_TYPE));
704+
updatedMapping.put(FIELD_TYPE, timestampType != null ? timestampType : DateFieldMapper.CONTENT_TYPE);
705+
if (sourceMapping.get("format") != null) {
706+
updatedMapping.put("format", sourceMapping.get("format"));
707+
}
708+
if (sourceMapping.get("ignore_malformed") != null) {
709+
updatedMapping.put("ignore_malformed", sourceMapping.get("ignore_malformed"));
710+
}
692711
updatedMapping.put("meta", Map.of(dateIntervalType, dateInterval, DownsampleConfig.TIME_ZONE, timezone));
693-
} else if (helper.isTimeSeriesMetric(field, mapping)) {
712+
return;
713+
}
714+
if (helper.isTimeSeriesMetric(fieldName, sourceMapping)) {
694715
final TimeSeriesParams.MetricType metricType = TimeSeriesParams.MetricType.fromString(
695-
mapping.get(TIME_SERIES_METRIC_PARAM).toString()
716+
sourceMapping.get(TIME_SERIES_METRIC_PARAM).toString()
696717
);
697718
if (metricType == TimeSeriesParams.MetricType.GAUGE
698-
&& AggregateMetricDoubleFieldMapper.CONTENT_TYPE.equals(mapping.get("type")) == false) {
699-
var supportedMetrics = getSupportedMetrics(metricType, mapping);
719+
&& AggregateMetricDoubleFieldMapper.CONTENT_TYPE.equals(sourceMapping.get(FIELD_TYPE)) == false) {
720+
var supportedMetrics = getSupportedMetrics(metricType, sourceMapping);
700721

701-
updatedMapping.clear();
702722
updatedMapping.put(TIME_SERIES_METRIC_PARAM, metricType.toString());
703-
updatedMapping.put("type", AggregateMetricDoubleFieldMapper.CONTENT_TYPE);
723+
updatedMapping.put(FIELD_TYPE, AggregateMetricDoubleFieldMapper.CONTENT_TYPE);
704724
updatedMapping.put(AggregateMetricDoubleFieldMapper.Names.METRICS, supportedMetrics.supportedMetrics);
705725
updatedMapping.put(AggregateMetricDoubleFieldMapper.Names.DEFAULT_METRIC, supportedMetrics.defaultMetric);
726+
return;
706727
}
707728
}
729+
for (String f : sourceMapping.keySet()) {
730+
if (f.equals(MAPPING_PROPERTIES) || f.equals(MULTI_FIELDS)) {
731+
continue;
732+
}
733+
updatedMapping.put(f, sourceMapping.get(f));
734+
}
708735
});
709-
return new CompressedXContent(sourceIndexMappings).uncompressed().utf8ToString();
736+
737+
return new CompressedXContent(downsampledMapping).uncompressed().utf8ToString();
738+
}
739+
740+
private static void populateMappingProperties(
741+
final Map<String, ?> sourceMapping,
742+
final Map<String, Object> destMapping,
743+
TriConsumer<String, Map<String, ?>, Map<String, Object>> fieldProcessor
744+
) {
745+
Object sourceProperties0 = sourceMapping.get(MAPPING_PROPERTIES);
746+
if (sourceProperties0 instanceof Map) {
747+
@SuppressWarnings("unchecked")
748+
Map<String, ?> sourceProperties = (Map<String, ?>) sourceProperties0;
749+
var destProperties = new HashMap<>(sourceProperties.size());
750+
destMapping.put(MAPPING_PROPERTIES, destProperties);
751+
for (Map.Entry<String, ?> entry : sourceProperties.entrySet()) {
752+
String fieldName = entry.getKey();
753+
final Object v = entry.getValue();
754+
if (v instanceof Map) {
755+
@SuppressWarnings("unchecked")
756+
Map<String, ?> sourceFieldMapping = (Map<String, ?>) v;
757+
var destFieldMapping = new HashMap<String, Object>(sourceFieldMapping.size());
758+
destProperties.put(fieldName, destFieldMapping);
759+
// Process the field from properties and multi-fields.
760+
fieldProcessor.apply(entry.getKey(), sourceFieldMapping, destFieldMapping);
761+
populateMappingProperties(sourceFieldMapping, destFieldMapping, fieldProcessor);
762+
763+
// Multi fields
764+
Object sourceFieldsO = sourceFieldMapping.get(MULTI_FIELDS);
765+
if (sourceFieldsO instanceof Map) {
766+
@SuppressWarnings("unchecked")
767+
Map<String, ?> sourceFields = (Map<String, ?>) sourceFieldsO;
768+
var destFields = new HashMap<String, Object>(sourceFields.size());
769+
destFieldMapping.put(MULTI_FIELDS, destFields);
770+
for (Map.Entry<String, ?> multiFieldEntry : sourceFields.entrySet()) {
771+
Object v2 = multiFieldEntry.getValue();
772+
if (v2 instanceof Map) {
773+
String multiFieldName = multiFieldEntry.getKey();
774+
@SuppressWarnings("unchecked")
775+
Map<String, ?> sourceMultiFieldMapping = (Map<String, ?>) v2;
776+
Map<String, Object> destMultiFieldMapping = new HashMap<>(sourceMultiFieldMapping.size());
777+
fieldProcessor.apply(multiFieldName, sourceMultiFieldMapping, destMultiFieldMapping);
778+
}
779+
}
780+
}
781+
}
782+
}
783+
}
710784
}
711785

712786
// public for testing
@@ -717,7 +791,7 @@ public static AggregateMetricDoubleFieldSupportedMetrics getSupportedMetrics(
717791
final TimeSeriesParams.MetricType metricType,
718792
final Map<String, ?> fieldProperties
719793
) {
720-
boolean sourceIsAggregate = fieldProperties.get("type").equals(AggregateMetricDoubleFieldMapper.CONTENT_TYPE);
794+
boolean sourceIsAggregate = fieldProperties.get(FIELD_TYPE).equals(AggregateMetricDoubleFieldMapper.CONTENT_TYPE);
721795
List<String> supportedAggs = List.of(metricType.supportedAggs());
722796

723797
if (sourceIsAggregate) {
@@ -834,11 +908,10 @@ static IndexMetadata.Builder copyIndexMetadata(
834908
/**
835909
* Configure the dynamic templates to always map strings to the keyword field type.
836910
*/
837-
private static void addDynamicTemplates(Map<String, Object> mapping) throws IOException {
838-
mapping.put(
839-
"dynamic_templates",
840-
List.of(Map.of("strings", Map.of("match_mapping_type", "string", "mapping", Map.of("type", "keyword"))))
841-
);
911+
private static void addDynamicTemplateForStrings(Map<String, Object> mapping) {
912+
List<Object> dynamicTemplates = new ArrayList<>();
913+
dynamicTemplates.add(Map.of("strings", Map.of("match_mapping_type", "string", "mapping", Map.of(FIELD_TYPE, "keyword"))));
914+
mapping.put(MAPPING_DYNAMIC_TEMPLATES, dynamicTemplates);
842915
}
843916

844917
private void createDownsampleIndex(

0 commit comments

Comments
 (0)