From dc236d473c786a5f739a0fe1bf052673da2112ec Mon Sep 17 00:00:00 2001 From: Augment Agent Date: Sat, 28 Feb 2026 01:02:50 +0000 Subject: [PATCH] Fix effective_mappings field to remove _doc wrapper The effective_mappings field in the get data stream mappings API (GetDataStreamMappingsAction) and update data stream mappings API (UpdateDataStreamMappingsAction) was incorrectly returning a _doc type wrapper that shouldn't be present according to the spec. This change strips the _doc wrapper from effective_mappings before returning it to the client, similar to how MappingMetadata.sourceAsMap() handles the type wrapper. Changes: - Modified GetDataStreamMappingsAction.DataStreamMappingsResponse.toXContent to strip _doc wrapper from effective_mappings - Modified UpdateDataStreamMappingsAction.DataStreamMappingsResponse.toXContent to strip _doc wrapper from effective_mappings - Updated YAML rest tests to expect effective_mappings without _doc wrapper The response now correctly returns: { "effective_mappings": { "properties": { ... } } } Instead of: { "effective_mappings": { "_doc": { "properties": { ... } } } } Related: https://augment-wic8570.slack.com/archives/C0AG2MXKEQJ/p1772239905420109 --- .../data_stream/250_data_stream_mappings.yml | 28 +++++++++---------- .../GetDataStreamMappingsAction.java | 4 +++ .../UpdateDataStreamMappingsAction.java | 4 +++ 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/modules/data-streams/src/yamlRestTest/resources/rest-api-spec/test/data_stream/250_data_stream_mappings.yml b/modules/data-streams/src/yamlRestTest/resources/rest-api-spec/test/data_stream/250_data_stream_mappings.yml index c0fef3e6bae07..5dc465d05a80a 100644 --- a/modules/data-streams/src/yamlRestTest/resources/rest-api-spec/test/data_stream/250_data_stream_mappings.yml +++ b/modules/data-streams/src/yamlRestTest/resources/rest-api-spec/test/data_stream/250_data_stream_mappings.yml @@ -34,7 +34,7 @@ setup: name: my-data-stream-1 - match: { data_streams.0.name: my-data-stream-1 } - match: { data_streams.0.mappings: {} } - - length: { data_streams.0.effective_mappings._doc.properties: 2 } + - length: { data_streams.0.effective_mappings.properties: 2 } - do: indices.get_data_stream: @@ -56,7 +56,7 @@ setup: - match: { data_streams.0.name: my-data-stream-1 } - match: { data_streams.0.applied_to_data_stream: true } - match: { data_streams.0.mappings.properties.name.type: "keyword" } - - match: { data_streams.0.effective_mappings._doc.properties.name.type: "keyword" } + - match: { data_streams.0.effective_mappings.properties.name.type: "keyword" } - do: indices.rollover: @@ -71,9 +71,9 @@ setup: indices.get_data_stream_mappings: name: my-data-stream-1 - match: { data_streams.0.name: my-data-stream-1 } - - length: { data_streams.0.effective_mappings._doc.properties: 3 } + - length: { data_streams.0.effective_mappings.properties: 3 } - match: { data_streams.0.mappings.properties.name.type: "keyword" } - - match: { data_streams.0.effective_mappings._doc.properties.name.type: "keyword" } + - match: { data_streams.0.effective_mappings.properties.name.type: "keyword" } - do: indices.get_data_stream: @@ -149,9 +149,9 @@ setup: - match: { data_streams.0.mappings.properties.field1.type: "text" } - match: { data_streams.0.mappings.properties.field2: null } - match: { data_streams.0.mappings.properties.field3.type: "text" } - - match: { data_streams.0.effective_mappings._doc.properties.field1.type: "text" } - - match: { data_streams.0.effective_mappings._doc.properties.field2.type: "keyword" } - - match: { data_streams.0.effective_mappings._doc.properties.field3.type: "text" } + - match: { data_streams.0.effective_mappings.properties.field1.type: "text" } + - match: { data_streams.0.effective_mappings.properties.field2.type: "keyword" } + - match: { data_streams.0.effective_mappings.properties.field3.type: "text" } - do: cluster.put_component_template: @@ -180,10 +180,10 @@ setup: indices.get_data_stream_mappings: name: my-component-only-data-stream-1 - match: { data_streams.0.name: my-component-only-data-stream-1 } - - length: { data_streams.0.effective_mappings._doc.properties: 5 } + - length: { data_streams.0.effective_mappings.properties: 5 } - match: { data_streams.0.mappings.properties.field1.type: "text" } - - match: { data_streams.0.effective_mappings._doc.properties.field3.type: "text" } - - match: { data_streams.0.effective_mappings._doc.properties.field4.type: "keyword" } + - match: { data_streams.0.effective_mappings.properties.field3.type: "text" } + - match: { data_streams.0.effective_mappings.properties.field4.type: "keyword" } - do: indices.get_data_stream: @@ -212,7 +212,7 @@ setup: - match: { data_streams.0.name: my-component-only-data-stream-1 } - match: { data_streams.0.applied_to_data_stream: true } - match: { data_streams.0.mappings null } - - match: { data_streams.0.effective_mappings._doc.properties.field1.type: "keyword" } - - match: { data_streams.0.effective_mappings._doc.properties.field2.type: "keyword" } - - match: { data_streams.0.effective_mappings._doc.properties.field3: null } - - match: { data_streams.0.effective_mappings._doc.properties.field4.type: "keyword" } + - match: { data_streams.0.effective_mappings.properties.field1.type: "keyword" } + - match: { data_streams.0.effective_mappings.properties.field2.type: "keyword" } + - match: { data_streams.0.effective_mappings.properties.field3: null } + - match: { data_streams.0.effective_mappings.properties.field4.type: "keyword" } diff --git a/server/src/main/java/org/elasticsearch/action/datastreams/GetDataStreamMappingsAction.java b/server/src/main/java/org/elasticsearch/action/datastreams/GetDataStreamMappingsAction.java index 5d81d44b7df70..ea6c6eb499cfd 100644 --- a/server/src/main/java/org/elasticsearch/action/datastreams/GetDataStreamMappingsAction.java +++ b/server/src/main/java/org/elasticsearch/action/datastreams/GetDataStreamMappingsAction.java @@ -131,6 +131,10 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws true, XContentType.JSON ).v2(); + // Strip the _doc wrapper if present + if (uncompressedEffectiveMappings.size() == 1 && uncompressedEffectiveMappings.containsKey("_doc")) { + uncompressedEffectiveMappings = (Map) uncompressedEffectiveMappings.get("_doc"); + } builder.field("effective_mappings"); builder.map(uncompressedEffectiveMappings); builder.endObject(); diff --git a/server/src/main/java/org/elasticsearch/action/datastreams/UpdateDataStreamMappingsAction.java b/server/src/main/java/org/elasticsearch/action/datastreams/UpdateDataStreamMappingsAction.java index 561e59f3eed36..5fd00cb2f9538 100644 --- a/server/src/main/java/org/elasticsearch/action/datastreams/UpdateDataStreamMappingsAction.java +++ b/server/src/main/java/org/elasticsearch/action/datastreams/UpdateDataStreamMappingsAction.java @@ -214,6 +214,10 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws XContentType.JSON ).v2(); if (uncompressedEffectiveMappings.isEmpty() == false) { + // Strip the _doc wrapper if present + if (uncompressedEffectiveMappings.size() == 1 && uncompressedEffectiveMappings.containsKey("_doc")) { + uncompressedEffectiveMappings = (Map) uncompressedEffectiveMappings.get("_doc"); + } builder.field("effective_mappings"); builder.map(uncompressedEffectiveMappings); }