Skip to content

Commit f7c2d7d

Browse files
committed
Adding a mapping_merge_reason parameter to the ingest simulate API
1 parent 593f48f commit f7c2d7d

File tree

9 files changed

+181
-30
lines changed

9 files changed

+181
-30
lines changed

qa/smoke-test-ingest-with-all-dependencies/src/yamlRestTest/resources/rest-api-spec/test/ingest/80_ingest_simulate.yml

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1931,3 +1931,81 @@ setup:
19311931
- match: { docs.0.doc._index: "simple-data-stream1" }
19321932
- match: { docs.0.doc._source.bar: "baz" }
19331933
- match: { docs.0.doc.error.type: "document_parsing_exception" }
1934+
1935+
---
1936+
"Test ingest simulate with mapping addition on subobjects":
1937+
1938+
- skip:
1939+
features:
1940+
- headers
1941+
- allowed_warnings
1942+
1943+
- do:
1944+
indices.put_index_template:
1945+
name: subobject-template
1946+
body:
1947+
index_patterns: subobject-index*
1948+
template:
1949+
mappings:
1950+
properties:
1951+
a.b:
1952+
type: match_only_text
1953+
1954+
- do:
1955+
headers:
1956+
Content-Type: application/json
1957+
simulate.ingest:
1958+
body: >
1959+
{
1960+
"docs": [
1961+
{
1962+
"_index": "subobject-index-1",
1963+
"_id": "AZgsHA0B41JjTOmNiBKC",
1964+
"_source": {
1965+
"a.b": "some text"
1966+
}
1967+
}
1968+
],
1969+
"mapping_addition": {
1970+
"properties": {
1971+
"a.b": {
1972+
"type": "keyword"
1973+
}
1974+
}
1975+
}
1976+
}
1977+
- length: { docs: 1 }
1978+
- match: { docs.0.doc._index: "subobject-index-1" }
1979+
- match: { docs.0.doc._source.a\.b: "some text" }
1980+
- match: { docs.0.doc.error.type: "mapper_parsing_exception" }
1981+
1982+
# Here we provide a mapping_substitution to the subobject, and make sure that it is applied rather than throwing an
1983+
# exception.
1984+
- do:
1985+
headers:
1986+
Content-Type: application/json
1987+
simulate.ingest:
1988+
mapping_merge_reason: "index_template"
1989+
body: >
1990+
{
1991+
"docs": [
1992+
{
1993+
"_index": "subobject-index-1",
1994+
"_id": "AZgsHA0B41JjTOmNiBKC",
1995+
"_source": {
1996+
"a.b": "some text"
1997+
}
1998+
}
1999+
],
2000+
"mapping_addition": {
2001+
"properties": {
2002+
"a.b": {
2003+
"type": "keyword"
2004+
}
2005+
}
2006+
}
2007+
}
2008+
- length: { docs: 1 }
2009+
- match: { docs.0.doc._index: "subobject-index-1" }
2010+
- match: { docs.0.doc._source.a\.b: "some text" }
2011+
- not_exists: docs.0.doc.error

rest-api-spec/src/main/resources/rest-api-spec/api/simulate.ingest.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
"pipeline":{
3939
"type":"string",
4040
"description":"The pipeline id to preprocess incoming documents with if no pipeline is given for a particular document"
41+
},
42+
"mapping_merge_reason":{
43+
"type":"string",
44+
"description":"The mapping merge reason if mapping overrides are being provided in mapping_addition, index_template_substitutions, or component_template_substitutions. The allowed values are one of mapping_update or index_template. The mapping_update option merges mappings the way they would be merged into an existing index. The index_template option merges mappings the way they would be merged into a template.",
45+
"default": "mapping_update"
4146
}
4247
},
4348
"body":{

server/src/main/java/org/elasticsearch/TransportVersions.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ static TransportVersion def(int id) {
355355
public static final TransportVersion PIPELINE_TRACKING_INFO = def(9_131_0_00);
356356
public static final TransportVersion COMPONENT_TEMPLATE_TRACKING_INFO = def(9_132_0_00);
357357
public static final TransportVersion TO_CHILD_BLOCK_JOIN_QUERY = def(9_133_0_00);
358+
public static final TransportVersion SIMULATE_INGEST_MAPPING_MERGE_REASON = def(9_134_0_00);
358359

359360
/*
360361
* STOP! READ THIS FIRST! No, really,

server/src/main/java/org/elasticsearch/action/bulk/SimulateBulkRequest.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ public class SimulateBulkRequest extends BulkRequest {
103103
private final Map<String, Map<String, Object>> componentTemplateSubstitutions;
104104
private final Map<String, Map<String, Object>> indexTemplateSubstitutions;
105105
private final Map<String, Object> mappingAddition;
106+
private final String mappingMergeReason;
106107

107108
/**
108109
* @param pipelineSubstitutions The pipeline definitions that are to be used in place of any pre-existing pipeline definitions with
@@ -118,7 +119,8 @@ public SimulateBulkRequest(
118119
Map<String, Map<String, Object>> pipelineSubstitutions,
119120
Map<String, Map<String, Object>> componentTemplateSubstitutions,
120121
Map<String, Map<String, Object>> indexTemplateSubstitutions,
121-
Map<String, Object> mappingAddition
122+
Map<String, Object> mappingAddition,
123+
String mappingMergeReason
122124
) {
123125
super();
124126
Objects.requireNonNull(pipelineSubstitutions);
@@ -129,6 +131,7 @@ public SimulateBulkRequest(
129131
this.componentTemplateSubstitutions = componentTemplateSubstitutions;
130132
this.indexTemplateSubstitutions = indexTemplateSubstitutions;
131133
this.mappingAddition = mappingAddition;
134+
this.mappingMergeReason = mappingMergeReason;
132135
}
133136

134137
@SuppressWarnings("unchecked")
@@ -147,6 +150,11 @@ public SimulateBulkRequest(StreamInput in) throws IOException {
147150
} else {
148151
mappingAddition = Map.of();
149152
}
153+
if (in.getTransportVersion().onOrAfter(TransportVersions.SIMULATE_INGEST_MAPPING_MERGE_REASON)) {
154+
mappingMergeReason = in.readOptionalString();
155+
} else {
156+
mappingMergeReason = null;
157+
}
150158
}
151159

152160
@Override
@@ -160,6 +168,9 @@ public void writeTo(StreamOutput out) throws IOException {
160168
if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_17_0)) {
161169
out.writeGenericValue(mappingAddition);
162170
}
171+
if (out.getTransportVersion().onOrAfter(TransportVersions.SIMULATE_INGEST_MAPPING_MERGE_REASON)) {
172+
out.writeOptionalString(mappingMergeReason);
173+
}
163174
}
164175

165176
public Map<String, Map<String, Object>> getPipelineSubstitutions() {
@@ -189,6 +200,10 @@ public Map<String, Object> getMappingAddition() {
189200
return mappingAddition;
190201
}
191202

203+
public String getMappingMergeReason() {
204+
return mappingMergeReason;
205+
}
206+
192207
private static ComponentTemplate convertRawTemplateToComponentTemplate(Map<String, Object> rawTemplate) {
193208
ComponentTemplate componentTemplate;
194209
try (var parser = XContentHelper.mapToXContentParser(XContentParserConfiguration.EMPTY, rawTemplate)) {
@@ -215,7 +230,8 @@ public BulkRequest shallowClone() {
215230
pipelineSubstitutions,
216231
componentTemplateSubstitutions,
217232
indexTemplateSubstitutions,
218-
mappingAddition
233+
mappingAddition,
234+
mappingMergeReason
219235
);
220236
bulkRequest.setRefreshPolicy(getRefreshPolicy());
221237
bulkRequest.waitForActiveShards(waitForActiveShards());

server/src/main/java/org/elasticsearch/action/bulk/TransportSimulateBulkAction.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ protected void doInternalExecute(
136136
Map<String, ComponentTemplate> componentTemplateSubstitutions = bulkRequest.getComponentTemplateSubstitutions();
137137
Map<String, ComposableIndexTemplate> indexTemplateSubstitutions = bulkRequest.getIndexTemplateSubstitutions();
138138
Map<String, Object> mappingAddition = ((SimulateBulkRequest) bulkRequest).getMappingAddition();
139+
MapperService.MergeReason mappingMergeReason = Optional.ofNullable(((SimulateBulkRequest) bulkRequest).getMappingMergeReason())
140+
.map(mergeReason -> MapperService.MergeReason.valueOf(mergeReason.toUpperCase()))
141+
.orElse(MapperService.MergeReason.MAPPING_UPDATE);
139142
for (int i = 0; i < bulkRequest.requests.size(); i++) {
140143
DocWriteRequest<?> docRequest = bulkRequest.requests.get(i);
141144
assert docRequest instanceof IndexRequest : "TransportSimulateBulkAction should only ever be called with IndexRequests";
@@ -144,7 +147,8 @@ protected void doInternalExecute(
144147
componentTemplateSubstitutions,
145148
indexTemplateSubstitutions,
146149
mappingAddition,
147-
request
150+
request,
151+
mappingMergeReason
148152
);
149153
Exception mappingValidationException = validationResult.v2();
150154
responses.set(
@@ -182,7 +186,8 @@ private Tuple<Collection<String>, Exception> validateMappings(
182186
Map<String, ComponentTemplate> componentTemplateSubstitutions,
183187
Map<String, ComposableIndexTemplate> indexTemplateSubstitutions,
184188
Map<String, Object> mappingAddition,
185-
IndexRequest request
189+
IndexRequest request,
190+
MapperService.MergeReason mappingMergeReason
186191
) {
187192
final SourceToParse sourceToParse = new SourceToParse(
188193
request.id(),
@@ -207,7 +212,7 @@ private Tuple<Collection<String>, Exception> validateMappings(
207212
IndexMetadata imd = project.getIndexSafe(indexAbstraction.getWriteIndex(request, project));
208213
CompressedXContent mappings = Optional.ofNullable(imd.mapping()).map(MappingMetadata::source).orElse(null);
209214
CompressedXContent mergedMappings = mappingAddition == null ? null : mergeMappings(mappings, mappingAddition);
210-
ignoredFields = validateUpdatedMappingsFromIndexMetadata(imd, mergedMappings, request, sourceToParse);
215+
ignoredFields = validateUpdatedMappingsFromIndexMetadata(imd, mergedMappings, request, sourceToParse, mappingMergeReason);
211216
} else {
212217
/*
213218
* The index did not exist, or we have component template substitutions, so we put together the mappings from existing
@@ -265,7 +270,7 @@ private Tuple<Collection<String>, Exception> validateMappings(
265270
);
266271
CompressedXContent mappings = template.mappings();
267272
CompressedXContent mergedMappings = mergeMappings(mappings, mappingAddition);
268-
ignoredFields = validateUpdatedMappings(mappings, mergedMappings, request, sourceToParse);
273+
ignoredFields = validateUpdatedMappings(mappings, mergedMappings, request, sourceToParse, mappingMergeReason);
269274
} else {
270275
List<IndexTemplateMetadata> matchingTemplates = findV1Templates(simulatedProjectMetadata, request.index(), false);
271276
if (matchingTemplates.isEmpty() == false) {
@@ -279,15 +284,15 @@ private Tuple<Collection<String>, Exception> validateMappings(
279284
xContentRegistry
280285
);
281286
final CompressedXContent combinedMappings = mergeMappings(new CompressedXContent(mappingsMap), mappingAddition);
282-
ignoredFields = validateUpdatedMappings(null, combinedMappings, request, sourceToParse);
287+
ignoredFields = validateUpdatedMappings(null, combinedMappings, request, sourceToParse, mappingMergeReason);
283288
} else {
284289
/*
285290
* The index matched no templates and had no mapping of its own. If there were component template substitutions
286291
* or index template substitutions, they didn't match anything. So just apply the mapping addition if it exists,
287292
* and validate.
288293
*/
289294
final CompressedXContent combinedMappings = mergeMappings(null, mappingAddition);
290-
ignoredFields = validateUpdatedMappings(null, combinedMappings, request, sourceToParse);
295+
ignoredFields = validateUpdatedMappings(null, combinedMappings, request, sourceToParse, mappingMergeReason);
291296
}
292297
}
293298
}
@@ -305,7 +310,8 @@ private Collection<String> validateUpdatedMappings(
305310
@Nullable CompressedXContent originalMappings,
306311
@Nullable CompressedXContent updatedMappings,
307312
IndexRequest request,
308-
SourceToParse sourceToParse
313+
SourceToParse sourceToParse,
314+
MapperService.MergeReason mappingMergeReason
309315
) throws IOException {
310316
Settings dummySettings = Settings.builder()
311317
.put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current())
@@ -318,14 +324,15 @@ private Collection<String> validateUpdatedMappings(
318324
originalIndexMetadataBuilder.putMapping(new MappingMetadata(originalMappings));
319325
}
320326
final IndexMetadata originalIndexMetadata = originalIndexMetadataBuilder.build();
321-
return validateUpdatedMappingsFromIndexMetadata(originalIndexMetadata, updatedMappings, request, sourceToParse);
327+
return validateUpdatedMappingsFromIndexMetadata(originalIndexMetadata, updatedMappings, request, sourceToParse, mappingMergeReason);
322328
}
323329

324330
private Collection<String> validateUpdatedMappingsFromIndexMetadata(
325331
IndexMetadata originalIndexMetadata,
326332
@Nullable CompressedXContent updatedMappings,
327333
IndexRequest request,
328-
SourceToParse sourceToParse
334+
SourceToParse sourceToParse,
335+
MapperService.MergeReason mappingMergeReason
329336
) throws IOException {
330337
if (updatedMappings == null) {
331338
return List.of(); // no validation to do
@@ -335,7 +342,7 @@ private Collection<String> validateUpdatedMappingsFromIndexMetadata(
335342
.putMapping(new MappingMetadata(updatedMappings))
336343
.build();
337344
Engine.Index result = indicesService.withTempIndexService(originalIndexMetadata, indexService -> {
338-
indexService.mapperService().merge(updatedIndexMetadata, MapperService.MergeReason.MAPPING_UPDATE);
345+
indexService.mapperService().merge(updatedIndexMetadata, mappingMergeReason);
339346
return IndexShard.prepareIndex(
340347
indexService.mapperService(),
341348
sourceToParse,

server/src/main/java/org/elasticsearch/rest/action/ingest/RestSimulateIngestAction.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC
8585
"index_template_substitutions"
8686
);
8787
Object mappingAddition = sourceMap.remove("mapping_addition");
88+
String mappingMergeReason = request.param("mapping_merge_reason");
8889
SimulateBulkRequest bulkRequest = new SimulateBulkRequest(
8990
pipelineSubstitutions == null ? Map.of() : pipelineSubstitutions,
9091
componentTemplateSubstitutions == null ? Map.of() : componentTemplateSubstitutions,
9192
indexTemplateSubstitutions == null ? Map.of() : indexTemplateSubstitutions,
92-
mappingAddition == null ? Map.of() : Map.of("_doc", mappingAddition)
93+
mappingAddition == null ? Map.of() : Map.of("_doc", mappingAddition),
94+
mappingMergeReason
9395
);
9496
BytesReference transformedData = convertToBulkRequestXContentBytes(sourceMap);
9597
bulkRequest.add(

0 commit comments

Comments
 (0)