Skip to content

Commit 2946355

Browse files
authored
Remove typename checks in mapping updates (#47347)
This commit removes types validation during mapping updates. This will make further work on types removal easier, as it will prevent test failures due to type-name clashes when we remove type information from PutMapping and CreateIndex requests Part of #41059
1 parent c74ca28 commit 2946355

File tree

5 files changed

+7
-166
lines changed

5 files changed

+7
-166
lines changed

rest-api-spec/src/main/resources/rest-api-spec/test/delete/70_mix_typeless_typeful.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,6 @@
1919
id: 1
2020
body: { foo: bar }
2121

22-
- do:
23-
catch: bad_request
24-
delete:
25-
index: index
26-
type: some_random_type
27-
id: 1
28-
29-
- match: { error.root_cause.0.reason: "/Rejecting.mapping.update.to.\\[index\\].as.the.final.mapping.would.have.more.than.1.type.*/" }
30-
3122
- do:
3223
delete:
3324
index: index

server/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,14 @@
4343
import org.elasticsearch.index.mapper.MapperService;
4444
import org.elasticsearch.index.mapper.MapperService.MergeReason;
4545
import org.elasticsearch.indices.IndicesService;
46-
import org.elasticsearch.indices.InvalidTypeNameException;
4746

4847
import java.io.IOException;
4948
import java.util.ArrayList;
50-
import java.util.Arrays;
5149
import java.util.Collections;
5250
import java.util.HashMap;
5351
import java.util.List;
5452
import java.util.Map;
5553

56-
import static org.elasticsearch.index.mapper.MapperService.isMappingSourceTyped;
5754
import static org.elasticsearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason.NO_LONGER_ASSIGNED;
5855

5956
/**
@@ -245,7 +242,7 @@ class PutMappingExecutor implements ClusterStateTaskExecutor<PutMappingClusterSt
245242

246243
private ClusterState applyRequest(ClusterState currentState, PutMappingClusterStateUpdateRequest request,
247244
Map<Index, MapperService> indexMapperServices) throws IOException {
248-
String mappingType = request.type();
245+
249246
CompressedXContent mappingUpdateSource = new CompressedXContent(request.source());
250247
final MetaData metaData = currentState.metaData();
251248
final List<IndexMetaData> updateList = new ArrayList<>();
@@ -260,32 +257,11 @@ private ClusterState applyRequest(ClusterState currentState, PutMappingClusterSt
260257
updateList.add(indexMetaData);
261258
// try and parse it (no need to add it here) so we can bail early in case of parsing exception
262259
DocumentMapper existingMapper = mapperService.documentMapper();
263-
String typeForUpdate = mapperService.getTypeForUpdate(mappingType, mappingUpdateSource);
264-
if (existingMapper != null && existingMapper.type().equals(typeForUpdate) == false) {
265-
throw new IllegalArgumentException("Rejecting mapping update to [" + mapperService.index().getName() +
266-
"] as the final mapping would have more than 1 type: " + Arrays.asList(existingMapper.type(), typeForUpdate));
267-
}
268-
269260
DocumentMapper newMapper = mapperService.parse(request.type(), mappingUpdateSource);
270261
if (existingMapper != null) {
271262
// first, simulate: just call merge and ignore the result
272263
existingMapper.merge(newMapper.mapping());
273264
}
274-
275-
276-
if (mappingType == null) {
277-
mappingType = newMapper.type();
278-
} else if (mappingType.equals(newMapper.type()) == false
279-
&& (isMappingSourceTyped(request.type(), mappingUpdateSource)
280-
|| mapperService.resolveDocumentType(mappingType).equals(newMapper.type()) == false)) {
281-
throw new InvalidTypeNameException("Type name provided does not match type name within mapping definition.");
282-
}
283-
}
284-
assert mappingType != null;
285-
286-
if (MapperService.SINGLE_MAPPING_NAME.equals(mappingType) == false
287-
&& mappingType.charAt(0) == '_') {
288-
throw new InvalidTypeNameException("Document mapping type name can't start with '_', found: [" + mappingType + "]");
289265
}
290266
MetaData.Builder builder = MetaData.builder(metaData);
291267
boolean updated = false;
@@ -296,13 +272,12 @@ private ClusterState applyRequest(ClusterState currentState, PutMappingClusterSt
296272
final Index index = indexMetaData.getIndex();
297273
final MapperService mapperService = indexMapperServices.get(index);
298274

299-
String typeForUpdate = mapperService.getTypeForUpdate(mappingType, mappingUpdateSource);
300275
CompressedXContent existingSource = null;
301-
DocumentMapper existingMapper = mapperService.documentMapper(typeForUpdate);
276+
DocumentMapper existingMapper = mapperService.documentMapper();
302277
if (existingMapper != null) {
303278
existingSource = existingMapper.mappingSource();
304279
}
305-
DocumentMapper mergedMapper = mapperService.merge(typeForUpdate, mappingUpdateSource, MergeReason.MAPPING_UPDATE);
280+
DocumentMapper mergedMapper = mapperService.merge(request.type(), mappingUpdateSource, MergeReason.MAPPING_UPDATE);
306281
CompressedXContent updatedSource = mergedMapper.mappingSource();
307282

308283
if (existingSource != null) {
@@ -321,9 +296,9 @@ private ClusterState applyRequest(ClusterState currentState, PutMappingClusterSt
321296
} else {
322297
updatedMapping = true;
323298
if (logger.isDebugEnabled()) {
324-
logger.debug("{} create_mapping [{}] with source [{}]", index, mappingType, updatedSource);
299+
logger.debug("{} create_mapping with source [{}]", index, updatedSource);
325300
} else if (logger.isInfoEnabled()) {
326-
logger.info("{} create_mapping [{}]", index, mappingType);
301+
logger.info("{} create_mapping", index);
327302
}
328303
}
329304

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

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@
7070
import java.util.LinkedHashMap;
7171
import java.util.List;
7272
import java.util.Map;
73-
import java.util.Objects;
7473
import java.util.Set;
7574
import java.util.function.Function;
7675
import java.util.function.Supplier;
@@ -303,7 +302,8 @@ public void merge(IndexMetaData indexMetaData, MergeReason reason) {
303302
}
304303

305304
public DocumentMapper merge(String type, CompressedXContent mappingSource, MergeReason reason) {
306-
return internalMerge(Collections.singletonMap(type, mappingSource), reason).get(type);
305+
// TODO change internalMerge() to return a single DocumentMapper rather than a Map
306+
return internalMerge(Collections.singletonMap(type, mappingSource), reason).values().iterator().next();
307307
}
308308

309309
private synchronized Map<String, DocumentMapper> internalMerge(IndexMetaData indexMetaData,
@@ -373,14 +373,6 @@ private synchronized Map<String, DocumentMapper> internalMerge(DocumentMapper ma
373373

374374
Map<String, DocumentMapper> results = new LinkedHashMap<>(2);
375375

376-
{
377-
if (mapper != null && this.mapper != null && Objects.equals(this.mapper.type(), mapper.type()) == false) {
378-
throw new IllegalArgumentException(
379-
"Rejecting mapping update to [" + index().getName() + "] as the final mapping would have more than 1 type: "
380-
+ Arrays.asList(this.mapper.type(), mapper.type()));
381-
}
382-
}
383-
384376
DocumentMapper newMapper = null;
385377
if (mapper != null) {
386378
// check naming
@@ -619,15 +611,6 @@ public static boolean isMappingSourceTyped(String type, CompressedXContent mappi
619611
return isMappingSourceTyped(type, root);
620612
}
621613

622-
/**
623-
* If the _type name is _doc and there is no _doc top-level key then this means that we
624-
* are handling a typeless call. In such a case, we override _doc with the actual type
625-
* name in the mappings. This allows to use typeless APIs on typed indices.
626-
*/
627-
public String getTypeForUpdate(String type, CompressedXContent mappingSource) {
628-
return isMappingSourceTyped(type, mappingSource) == false ? resolveDocumentType(type) : type;
629-
}
630-
631614
/**
632615
* Resolves a type from a mapping-related request into the type that should be used when
633616
* merging and updating mappings.

server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataMappingServiceTests.java

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,11 @@
1919

2020
package org.elasticsearch.cluster.metadata;
2121

22-
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
2322
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingClusterStateUpdateRequest;
2423
import org.elasticsearch.cluster.ClusterState;
2524
import org.elasticsearch.cluster.ClusterStateTaskExecutor;
2625
import org.elasticsearch.cluster.service.ClusterService;
27-
import org.elasticsearch.common.Strings;
2826
import org.elasticsearch.common.compress.CompressedXContent;
29-
import org.elasticsearch.common.xcontent.XContentBuilder;
30-
import org.elasticsearch.common.xcontent.XContentFactory;
3127
import org.elasticsearch.index.Index;
3228
import org.elasticsearch.index.IndexService;
3329
import org.elasticsearch.index.mapper.MapperService;
@@ -38,7 +34,6 @@
3834
import java.util.Collection;
3935
import java.util.Collections;
4036

41-
import static org.hamcrest.CoreMatchers.containsString;
4237
import static org.hamcrest.Matchers.equalTo;
4338
import static org.hamcrest.Matchers.not;
4439

@@ -140,76 +135,4 @@ public void testMappingUpdateAccepts_docAsType() throws Exception {
140135
Collections.singletonMap("type", "keyword"))), mappingMetaData.sourceAsMap());
141136
}
142137

143-
public void testForbidMultipleTypes() throws Exception {
144-
CreateIndexRequestBuilder createIndexRequest = client().admin().indices()
145-
.prepareCreate("test")
146-
.addMapping(MapperService.SINGLE_MAPPING_NAME);
147-
IndexService indexService = createIndex("test", createIndexRequest);
148-
149-
MetaDataMappingService mappingService = getInstanceFromNode(MetaDataMappingService.class);
150-
ClusterService clusterService = getInstanceFromNode(ClusterService.class);
151-
152-
PutMappingClusterStateUpdateRequest request = new PutMappingClusterStateUpdateRequest()
153-
.type("other_type")
154-
.indices(new Index[] {indexService.index()})
155-
.source(Strings.toString(XContentFactory.jsonBuilder()
156-
.startObject()
157-
.startObject("other_type").endObject()
158-
.endObject()));
159-
ClusterStateTaskExecutor.ClusterTasksResult<PutMappingClusterStateUpdateRequest> result =
160-
mappingService.putMappingExecutor.execute(clusterService.state(), Collections.singletonList(request));
161-
assertThat(result.executionResults.size(), equalTo(1));
162-
163-
ClusterStateTaskExecutor.TaskResult taskResult = result.executionResults.values().iterator().next();
164-
assertFalse(taskResult.isSuccess());
165-
assertThat(taskResult.getFailure().getMessage(), containsString(
166-
"Rejecting mapping update to [test] as the final mapping would have more than 1 type: "));
167-
}
168-
169-
/**
170-
* This test checks that the multi-type validation is done before we do any other kind of validation
171-
* on the mapping that's added, see https://github.com/elastic/elasticsearch/issues/29313
172-
*/
173-
public void testForbidMultipleTypesWithConflictingMappings() throws Exception {
174-
XContentBuilder mapping = XContentFactory.jsonBuilder().startObject()
175-
.startObject(MapperService.SINGLE_MAPPING_NAME)
176-
.startObject("properties")
177-
.startObject("field1")
178-
.field("type", "text")
179-
.endObject()
180-
.endObject()
181-
.endObject()
182-
.endObject();
183-
184-
CreateIndexRequestBuilder createIndexRequest = client().admin().indices()
185-
.prepareCreate("test")
186-
.addMapping(MapperService.SINGLE_MAPPING_NAME, mapping);
187-
IndexService indexService = createIndex("test", createIndexRequest);
188-
189-
MetaDataMappingService mappingService = getInstanceFromNode(MetaDataMappingService.class);
190-
ClusterService clusterService = getInstanceFromNode(ClusterService.class);
191-
192-
String conflictingMapping = Strings.toString(XContentFactory.jsonBuilder().startObject()
193-
.startObject("other_type")
194-
.startObject("properties")
195-
.startObject("field1")
196-
.field("type", "keyword")
197-
.endObject()
198-
.endObject()
199-
.endObject()
200-
.endObject());
201-
202-
PutMappingClusterStateUpdateRequest request = new PutMappingClusterStateUpdateRequest()
203-
.type("other_type")
204-
.indices(new Index[] {indexService.index()})
205-
.source(conflictingMapping);
206-
ClusterStateTaskExecutor.ClusterTasksResult<PutMappingClusterStateUpdateRequest> result =
207-
mappingService.putMappingExecutor.execute(clusterService.state(), Collections.singletonList(request));
208-
assertThat(result.executionResults.size(), equalTo(1));
209-
210-
ClusterStateTaskExecutor.TaskResult taskResult = result.executionResults.values().iterator().next();
211-
assertFalse(taskResult.isSuccess());
212-
assertThat(taskResult.getFailure().getMessage(), containsString(
213-
"Rejecting mapping update to [test] as the final mapping would have more than 1 type: "));
214-
}
215138
}

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

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@
5454
import java.util.Map;
5555

5656
import static org.hamcrest.CoreMatchers.containsString;
57-
import static org.hamcrest.CoreMatchers.startsWith;
5857
import static org.hamcrest.Matchers.instanceOf;
5958

6059
public class MapperServiceTests extends ESSingleNodeTestCase {
@@ -267,36 +266,6 @@ public void testTotalFieldsLimitWithFieldAlias() throws Throwable {
267266
assertEquals("Limit of total fields [" + numberOfNonAliasFields + "] in index [test2] has been exceeded", e.getMessage());
268267
}
269268

270-
public void testForbidMultipleTypes() throws IOException {
271-
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type").endObject().endObject());
272-
MapperService mapperService = createIndex("test").mapperService();
273-
mapperService.merge("type", new CompressedXContent(mapping), MergeReason.MAPPING_UPDATE);
274-
275-
String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type2").endObject().endObject());
276-
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
277-
() -> mapperService.merge("type2", new CompressedXContent(mapping2), MergeReason.MAPPING_UPDATE));
278-
assertThat(e.getMessage(), startsWith("Rejecting mapping update to [test] as the final mapping would have more than 1 type: "));
279-
}
280-
281-
/**
282-
* This test checks that the multi-type validation is done before we do any other kind of validation on the mapping that's added,
283-
* see https://github.com/elastic/elasticsearch/issues/29313
284-
*/
285-
public void testForbidMultipleTypesWithConflictingMappings() throws IOException {
286-
String mapping = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type")
287-
.startObject("properties").startObject("field1").field("type", "integer_range")
288-
.endObject().endObject().endObject().endObject());
289-
MapperService mapperService = createIndex("test").mapperService();
290-
mapperService.merge("type", new CompressedXContent(mapping), MergeReason.MAPPING_UPDATE);
291-
292-
String mapping2 = Strings.toString(XContentFactory.jsonBuilder().startObject().startObject("type2")
293-
.startObject("properties").startObject("field1").field("type", "integer")
294-
.endObject().endObject().endObject().endObject());
295-
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
296-
() -> mapperService.merge("type2", new CompressedXContent(mapping2), MergeReason.MAPPING_UPDATE));
297-
assertThat(e.getMessage(), startsWith("Rejecting mapping update to [test] as the final mapping would have more than 1 type: "));
298-
}
299-
300269
public void testFieldNameLengthLimit() throws Throwable {
301270
int maxFieldNameLength = randomIntBetween(15, 20);
302271
String testString = new String(new char[maxFieldNameLength + 1]).replace("\0", "a");

0 commit comments

Comments
 (0)