Skip to content

Commit

Permalink
Give precedence to index creation when mixing typed templates with ty…
Browse files Browse the repository at this point in the history
…peless index creation and vice-versa.

Currently if you mix typed templates and typeless index creation or typeless
templates and typed index creation then you will end up with an error because
Elasticsearch tries to create an index that has multiple types: `_doc` and
the explicit type name that you used.

This commit proposes to give precedence to the index creation call so that
the type from the template will be ignored if the index creation call is
typeless while the template is typed, and the type from the index creation
call will be used if there is a typeless template.

This is consistent with the fact that index creation already "wins" if a field
is defined differently in the index creation call and in a template: the
definition from the index creation call is used in such cases.

Closes elastic#37773
  • Loading branch information
jpountz committed Jan 25, 2019
1 parent 170d741 commit 69f0b1e
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
"Create a typeless index while there is a typed template":

- skip:
version: " - 6.99.99"
reason: needs change to be backported to 6.7

- do:
indices.put_template:
include_type_name: true
name: test_template
body:
index_patterns: test-*
mappings:
my_type:
properties:
foo:
type: keyword

- do:
indices.create:
include_type_name: false
index: test-1
body:
mappings:
properties:
bar:
type: "long"

- do:
indices.get_mapping:
include_type_name: true
index: test-1

- is_true: test-1.mappings._doc # the index creation call won
- is_false: test-1.mappings.my_type
- is_true: test-1.mappings._doc.properties.foo
- is_true: test-1.mappings._doc.properties.bar

---
"Create a typed index while there is a typeless template":

- skip:
version: " - 6.99.99"
reason: needs change to be backported to 6.7

- do:
indices.put_template:
include_type_name: false
name: test_template
body:
index_patterns: test-*
mappings:
properties:
foo:
type: keyword

- do:
indices.create:
include_type_name: true
index: test-1
body:
mappings:
my_type:
properties:
bar:
type: "long"

- do:
indices.get_mapping:
include_type_name: true
index: test-1

- is_true: test-1.mappings.my_type # the index creation call won
- is_false: test-1.mappings._doc
- is_true: test-1.mappings.my_type.properties.foo
- is_true: test-1.mappings.my_type.properties.bar
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,21 @@ public ClusterState execute(ClusterState currentState) throws Exception {
if (mappings.containsKey(cursor.key)) {
XContentHelper.mergeDefaults(mappings.get(cursor.key),
MapperService.parseMapping(xContentRegistry, mappingString));
} else if (template.mappings().size() == 1 &&
(cursor.key.equals(MapperService.SINGLE_MAPPING_NAME) ||
mappings.containsKey(MapperService.SINGLE_MAPPING_NAME))) {
// The user is mixing a typeless index creation call with a typed template or vice-versa.
// In such cases we give precedence to the index creation call.
Map<String, Object> templateMapping = MapperService.parseMapping(xContentRegistry, mappingString);
assert templateMapping.size() == 1 : templateMapping.size();
assert cursor.key.equals(templateMapping.keySet().iterator().next()) :
cursor.key + " != " + templateMapping;
for (Map.Entry<String, Map<String, Object>> mappingEntry : mappings.entrySet()) {
templateMapping = Collections.singletonMap(
mappingEntry.getKey(), // reuse type name from the mapping
templateMapping.values().iterator().next()); // but actual mappings from the template
XContentHelper.mergeDefaults(mappingEntry.getValue(), templateMapping);
}
} else {
mappings.put(cursor.key,
MapperService.parseMapping(xContentRegistry, mappingString));
Expand Down

0 comments on commit 69f0b1e

Please sign in to comment.