Skip to content

Commit fbc7bbc

Browse files
authored
[8.18] Avoid serializing empty _source fields in mappings. (#124198)
Backporting #122606 to 8.18 branch.
1 parent ec0b615 commit fbc7bbc

File tree

16 files changed

+173
-77
lines changed

16 files changed

+173
-77
lines changed

docs/changelog/122606.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 122606
2+
summary: Avoid serializing empty `_source` fields in mappings
3+
area: Mapping
4+
type: bug
5+
issues: []

qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartDownsampleIT.java

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import com.carrotsearch.randomizedtesting.annotations.Name;
1313

14+
import org.elasticsearch.Version;
1415
import org.elasticsearch.client.Request;
1516
import org.elasticsearch.client.Response;
1617
import org.elasticsearch.common.Strings;
@@ -44,16 +45,26 @@ public class FullClusterRestartDownsampleIT extends ParameterizedFullClusterRest
4445

4546
protected static LocalClusterConfigProvider clusterConfig = c -> {};
4647

47-
private static ElasticsearchCluster cluster = ElasticsearchCluster.local()
48-
.distribution(DistributionType.DEFAULT)
49-
.version(getOldClusterTestVersion())
50-
.nodes(2)
51-
.setting("xpack.security.enabled", "false")
52-
.setting("indices.lifecycle.poll_interval", "5s")
53-
.apply(() -> clusterConfig)
54-
.feature(FeatureFlag.TIME_SERIES_MODE)
55-
.feature(FeatureFlag.FAILURE_STORE_ENABLED)
56-
.build();
48+
private static ElasticsearchCluster cluster = buildCluster();
49+
50+
private static ElasticsearchCluster buildCluster() {
51+
Version oldVersion = Version.fromString(OLD_CLUSTER_VERSION);
52+
var cluster = ElasticsearchCluster.local()
53+
.distribution(DistributionType.DEFAULT)
54+
.version(getOldClusterTestVersion())
55+
.nodes(2)
56+
.setting("xpack.security.enabled", "false")
57+
.setting("indices.lifecycle.poll_interval", "5s")
58+
.apply(() -> clusterConfig)
59+
.feature(FeatureFlag.TIME_SERIES_MODE)
60+
.feature(FeatureFlag.FAILURE_STORE_ENABLED);
61+
62+
if (oldVersion.before(Version.fromString("8.18.0"))) {
63+
cluster.jvmArg("-da:org.elasticsearch.index.mapper.DocumentMapper");
64+
cluster.jvmArg("-da:org.elasticsearch.index.mapper.MapperService");
65+
}
66+
return cluster.build();
67+
}
5768

5869
@ClassRule
5970
public static TestRule ruleChain = RuleChain.outerRule(repoDirectory).around(cluster);

qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/FullClusterRestartIT.java

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
import org.apache.http.util.EntityUtils;
1717
import org.elasticsearch.Build;
18+
import org.elasticsearch.Version;
1819
import org.elasticsearch.action.admin.cluster.settings.RestClusterGetSettingsResponse;
1920
import org.elasticsearch.client.Request;
2021
import org.elasticsearch.client.Response;
@@ -108,18 +109,28 @@ public class FullClusterRestartIT extends ParameterizedFullClusterRestartTestCas
108109

109110
protected static LocalClusterConfigProvider clusterConfig = c -> {};
110111

111-
private static ElasticsearchCluster cluster = ElasticsearchCluster.local()
112-
.distribution(DistributionType.DEFAULT)
113-
.version(getOldClusterTestVersion())
114-
.nodes(2)
115-
.setting("path.repo", () -> repoDirectory.getRoot().getPath())
116-
.setting("xpack.security.enabled", "false")
117-
// some tests rely on the translog not being flushed
118-
.setting("indices.memory.shard_inactive_time", "60m")
119-
.apply(() -> clusterConfig)
120-
.feature(FeatureFlag.TIME_SERIES_MODE)
121-
.feature(FeatureFlag.FAILURE_STORE_ENABLED)
122-
.build();
112+
private static ElasticsearchCluster cluster = buildCluster();
113+
114+
private static ElasticsearchCluster buildCluster() {
115+
Version oldVersion = Version.fromString(OLD_CLUSTER_VERSION);
116+
var cluster = ElasticsearchCluster.local()
117+
.distribution(DistributionType.DEFAULT)
118+
.version(getOldClusterTestVersion())
119+
.nodes(2)
120+
.setting("path.repo", () -> repoDirectory.getRoot().getPath())
121+
.setting("xpack.security.enabled", "false")
122+
// some tests rely on the translog not being flushed
123+
.setting("indices.memory.shard_inactive_time", "60m")
124+
.apply(() -> clusterConfig)
125+
.feature(FeatureFlag.TIME_SERIES_MODE)
126+
.feature(FeatureFlag.FAILURE_STORE_ENABLED);
127+
128+
if (oldVersion.before(Version.fromString("8.18.0"))) {
129+
cluster.jvmArg("-da:org.elasticsearch.index.mapper.DocumentMapper");
130+
cluster.jvmArg("-da:org.elasticsearch.index.mapper.MapperService");
131+
}
132+
return cluster.build();
133+
}
123134

124135
@ClassRule
125136
public static TestRule ruleChain = RuleChain.outerRule(repoDirectory).around(cluster);

qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/LogsIndexModeFullClusterRestartIT.java

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import com.carrotsearch.randomizedtesting.annotations.Name;
1313

14+
import org.elasticsearch.Version;
1415
import org.elasticsearch.client.Request;
1516
import org.elasticsearch.client.Response;
1617
import org.elasticsearch.client.RestClient;
@@ -33,17 +34,27 @@
3334
public class LogsIndexModeFullClusterRestartIT extends ParameterizedFullClusterRestartTestCase {
3435

3536
@ClassRule
36-
public static final ElasticsearchCluster cluster = ElasticsearchCluster.local()
37-
.distribution(DistributionType.DEFAULT)
38-
.version(getOldClusterTestVersion())
39-
.module("constant-keyword")
40-
.module("data-streams")
41-
.module("mapper-extras")
42-
.module("x-pack-aggregate-metric")
43-
.module("x-pack-stack")
44-
.setting("xpack.security.enabled", "false")
45-
.setting("xpack.license.self_generated.type", "trial")
46-
.build();
37+
public static final ElasticsearchCluster cluster = buildCluster();
38+
39+
private static ElasticsearchCluster buildCluster() {
40+
Version oldVersion = Version.fromString(OLD_CLUSTER_VERSION);
41+
var cluster = ElasticsearchCluster.local()
42+
.distribution(DistributionType.DEFAULT)
43+
.version(getOldClusterTestVersion())
44+
.module("constant-keyword")
45+
.module("data-streams")
46+
.module("mapper-extras")
47+
.module("x-pack-aggregate-metric")
48+
.module("x-pack-stack")
49+
.setting("xpack.security.enabled", "false")
50+
.setting("xpack.license.self_generated.type", "trial");
51+
52+
if (oldVersion.before(Version.fromString("8.18.0"))) {
53+
cluster.jvmArg("-da:org.elasticsearch.index.mapper.DocumentMapper");
54+
cluster.jvmArg("-da:org.elasticsearch.index.mapper.MapperService");
55+
}
56+
return cluster.build();
57+
}
4758

4859
public LogsIndexModeFullClusterRestartIT(@Name("cluster") FullClusterRestartUpgradeStatus upgradeStatus) {
4960
super(upgradeStatus);

qa/full-cluster-restart/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedFullClusterRestartTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
@TestCaseOrdering(FullClusterRestartTestOrdering.class)
3939
public abstract class ParameterizedFullClusterRestartTestCase extends ESRestTestCase {
4040
private static final Version MINIMUM_WIRE_COMPATIBLE_VERSION = Version.fromString("7.17.0");
41-
private static final String OLD_CLUSTER_VERSION = System.getProperty("tests.old_cluster_version");
41+
protected static final String OLD_CLUSTER_VERSION = System.getProperty("tests.old_cluster_version");
4242
private static IndexVersion oldIndexVersion;
4343
private static boolean upgradeFailed = false;
4444
private static boolean upgraded = false;

qa/mixed-cluster/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ buildParams.bwcVersions.withWireCompatible { bwcVersion, baseName ->
8585
setting 'health.master_history.no_master_transitions_threshold', '10'
8686
}
8787
requiresFeature 'es.index_mode_feature_flag_registered', Version.fromString("8.0.0")
88+
if (bwcVersion.before(Version.fromString("8.18.0"))) {
89+
jvmArgs '-da:org.elasticsearch.index.mapper.DocumentMapper'
90+
jvmArgs '-da:org.elasticsearch.index.mapper.MapperService'
91+
}
8892
}
8993

9094
tasks.register("${baseName}#mixedClusterTest", StandaloneRestIntegTestTask) {

qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/AbstractRollingUpgradeTestCase.java

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.elasticsearch.test.cluster.ElasticsearchCluster;
1616
import org.elasticsearch.test.cluster.FeatureFlag;
1717
import org.elasticsearch.test.cluster.local.distribution.DistributionType;
18+
import org.elasticsearch.test.cluster.util.Version;
1819
import org.junit.ClassRule;
1920
import org.junit.rules.RuleChain;
2021
import org.junit.rules.TemporaryFolder;
@@ -26,20 +27,30 @@ public abstract class AbstractRollingUpgradeTestCase extends ParameterizedRollin
2627

2728
private static final TemporaryFolder repoDirectory = new TemporaryFolder();
2829

29-
private static final ElasticsearchCluster cluster = ElasticsearchCluster.local()
30-
.distribution(DistributionType.DEFAULT)
31-
.version(getOldClusterTestVersion())
32-
.nodes(NODE_NUM)
33-
.setting("path.repo", new Supplier<>() {
34-
@Override
35-
@SuppressForbidden(reason = "TemporaryFolder only has io.File methods, not nio.File")
36-
public String get() {
37-
return repoDirectory.getRoot().getPath();
38-
}
39-
})
40-
.setting("xpack.security.enabled", "false")
41-
.feature(FeatureFlag.TIME_SERIES_MODE)
42-
.build();
30+
private static final ElasticsearchCluster cluster = buildCluster();
31+
32+
private static ElasticsearchCluster buildCluster() {
33+
Version oldVersion = Version.fromString(OLD_CLUSTER_VERSION);
34+
var cluster = ElasticsearchCluster.local()
35+
.distribution(DistributionType.DEFAULT)
36+
.version(getOldClusterTestVersion())
37+
.nodes(NODE_NUM)
38+
.setting("path.repo", new Supplier<>() {
39+
@Override
40+
@SuppressForbidden(reason = "TemporaryFolder only has io.File methods, not nio.File")
41+
public String get() {
42+
return repoDirectory.getRoot().getPath();
43+
}
44+
})
45+
.setting("xpack.security.enabled", "false")
46+
.feature(FeatureFlag.TIME_SERIES_MODE);
47+
48+
if (oldVersion.before(Version.fromString("8.18.0"))) {
49+
cluster.jvmArg("-da:org.elasticsearch.index.mapper.DocumentMapper");
50+
cluster.jvmArg("-da:org.elasticsearch.index.mapper.MapperService");
51+
}
52+
return cluster.build();
53+
}
4354

4455
@ClassRule
4556
public static TestRule ruleChain = RuleChain.outerRule(repoDirectory).around(cluster);

qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/ParameterizedRollingUpgradeTestCase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636

3737
public abstract class ParameterizedRollingUpgradeTestCase extends ESRestTestCase {
3838
protected static final int NODE_NUM = 3;
39-
private static final String OLD_CLUSTER_VERSION = System.getProperty("tests.old_cluster_version");
39+
protected static final String OLD_CLUSTER_VERSION = System.getProperty("tests.old_cluster_version");
4040
private static final Set<Integer> upgradedNodes = new HashSet<>();
4141
private static TestFeatureService oldClusterTestFeatureService = null;
4242
private static boolean upgradeFailed = false;

server/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,14 +172,18 @@ public Builder(IndexMode indexMode, final Settings settings, boolean supportsChe
172172
this.supportsNonDefaultParameterValues = supportsCheckForNonDefaultParams == false
173173
|| settings.getAsBoolean(LOSSY_PARAMETERS_ALLOWED_SETTING_NAME, true);
174174
this.serializeMode = serializeMode;
175-
this.mode = new Parameter<>(
176-
"mode",
177-
true,
178-
() -> null,
179-
(n, c, o) -> Mode.valueOf(o.toString().toUpperCase(Locale.ROOT)),
180-
m -> toType(m).enabled.explicit() ? null : toType(m).mode,
175+
this.mode = new Parameter<>("mode", true, () -> null, (n, c, o) -> Mode.valueOf(o.toString().toUpperCase(Locale.ROOT)), m -> {
176+
var sfm = toType(m);
177+
if (sfm.enabled.explicit()) {
178+
return null;
179+
} else if (sfm.serializeMode) {
180+
return sfm.mode;
181+
} else {
182+
return null;
183+
}
184+
},
181185
(b, n, v) -> b.field(n, v.toString().toLowerCase(Locale.ROOT)),
182-
v -> v.toString().toLowerCase(Locale.ROOT)
186+
v -> v != null ? v.toString().toLowerCase(Locale.ROOT) : null
183187
).setMergeValidator((previous, current, conflicts) -> (previous == current) || current != Mode.STORED)
184188
// don't emit if `enabled` is configured
185189
.setSerializerCheck((includeDefaults, isConfigured, value) -> serializeMode && value != null);
@@ -300,11 +304,20 @@ private static SourceFieldMapper resolveStaticInstance(final Mode sourceMode) {
300304
if (indexMode == IndexMode.STANDARD && settingSourceMode == Mode.STORED) {
301305
return DEFAULT;
302306
}
307+
SourceFieldMapper sourceFieldMapper;
303308
if (c.indexVersionCreated().onOrAfter(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER)) {
304-
return resolveStaticInstance(settingSourceMode);
309+
sourceFieldMapper = resolveStaticInstance(settingSourceMode);
305310
} else {
306-
return new SourceFieldMapper(settingSourceMode, Explicit.IMPLICIT_TRUE, Strings.EMPTY_ARRAY, Strings.EMPTY_ARRAY, true);
311+
sourceFieldMapper = new SourceFieldMapper(
312+
settingSourceMode,
313+
Explicit.IMPLICIT_TRUE,
314+
Strings.EMPTY_ARRAY,
315+
Strings.EMPTY_ARRAY,
316+
true
317+
);
307318
}
319+
indexMode.validateSourceFieldMapper(sourceFieldMapper);
320+
return sourceFieldMapper;
308321
},
309322
c -> new Builder(
310323
c.getIndexSettings().getMode(),

server/src/test/java/org/elasticsearch/index/mapper/SourceFieldMapperTests.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,14 @@ public void testSyntheticSourceInTimeSeries() throws IOException {
253253
});
254254
DocumentMapper mapper = createTimeSeriesModeDocumentMapper(mapping);
255255
assertTrue(mapper.sourceMapper().isSynthetic());
256-
assertEquals("{\"_source\":{}}", mapper.sourceMapper().toString());
256+
assertEquals("{}", mapper.sourceMapper().toString());
257257
}
258258

259259
public void testSyntheticSourceWithLogsIndexMode() throws IOException {
260260
XContentBuilder mapping = fieldMapping(b -> { b.field("type", "keyword"); });
261261
DocumentMapper mapper = createLogsModeDocumentMapper(mapping);
262262
assertTrue(mapper.sourceMapper().isSynthetic());
263-
assertEquals("{\"_source\":{}}", mapper.sourceMapper().toString());
263+
assertEquals("{}", mapper.sourceMapper().toString());
264264
}
265265

266266
public void testSupportsNonDefaultParameterValues() throws IOException {

0 commit comments

Comments
 (0)