Skip to content

Commit

Permalink
Make _doc work as an alias of the actual type of an index. (#39505)
Browse files Browse the repository at this point in the history
This is similar to the work that has been done on 7.x to make typeless API calls
work on indices that have types, except that this commit doesn't introduce
typeless calls, eg. the REST API spec or REST handlers haven't been updated.

It only affects the get, index, update, delete and bulk APIs. Other APIs that
require types such as explain or termvectors are left unchanged.

This is necesarry to allow for rolling upgrades from 6.7 to 7.x while internal
indices might remain queried during upgrade by nodes that are on either version.

Closes #39469
  • Loading branch information
jpountz authored Mar 1, 2019
1 parent 1976441 commit f14405a
Show file tree
Hide file tree
Showing 22 changed files with 669 additions and 33 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
"bulk without types on an index that has types":

- skip:
version: " - 6.6.99"
reason: Typeless APIs were introduced in 6.7.0

- do:
indices.create: # not using include_type_name: false on purpose
include_type_name: true
index: index
body:
mappings:
not_doc:
properties:
foo:
type: "keyword"
- do:
bulk:
refresh: true
body:
- index:
_index: index
_type: _doc
_id: 0
- foo: bar
- index:
_index: index
_type: _doc
_id: 1
- foo: bar

- do:
count:
index: index

- match: {count: 2}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
"DELETE with typeless API on an index that has types":

- skip:
version: " - 6.6.99"
reason: Typeless APIs were introduced in 6.7.0

- do:
indices.create: # not using include_type_name: false on purpose
include_type_name: true
index: index
body:
mappings:
not_doc:
properties:
foo:
type: "keyword"

- do:
index:
index: index
type: not_doc
id: 1
body: { foo: bar }

- do:
catch: bad_request
delete:
index: index
type: some_random_type
id: 1

- match: { error.root_cause.0.reason: "/Rejecting.mapping.update.to.\\[index\\].as.the.final.mapping.would.have.more.than.1.type.*/" }

- do:
delete:
index: index
type: _doc
id: 1

- match: { _index: "index" }
- match: { _type: "_doc" }
- match: { _id: "1"}
- match: { _version: 2}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
"GET with typeless API on an index that has types":

- skip:
version: " - 6.6.99"
reason: Typeless APIs were introduced in 6.7.0

- do:
indices.create: # not using include_type_name: false on purpose
include_type_name: true
index: index
body:
mappings:
not_doc:
properties:
foo:
type: "keyword"

- do:
index:
index: index
type: not_doc
id: 1
body: { foo: bar }

- do:
catch: missing
get:
index: index
type: some_random_type
id: 1

- match: { _index: "index" }
- match: { _type: "some_random_type" }
- match: { _id: "1"}
- match: { found: false}

- do:
get:
index: index
type: _doc
id: 1

- match: { _index: "index" }
- match: { _type: "_doc" }
- match: { _id: "1"}
- match: { _version: 1}
- match: { _source: { foo: bar }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
---
"Index with typeless API on an index that has types":

- skip:
version: " - 6.6.99"
reason: Typeless APIs were introduced in 6.7.0

- do:
indices.create: # not using include_type_name: false on purpose
include_type_name: true
index: index
body:
mappings:
not_doc:
properties:
foo:
type: "keyword"

- do:
index:
index: index
type: _doc
id: 1
body: { foo: bar }

- match: { _index: "index" }
- match: { _type: "_doc" }
- match: { _id: "1"}
- match: { _version: 1}

- do:
get: # not using typeless API on purpose
index: index
type: not_doc
id: 1

- match: { _index: "index" }
- match: { _type: "not_doc" } # the important bit to check
- match: { _id: "1"}
- match: { _version: 1}
- match: { _source: { foo: bar }}


- do:
index:
index: index
type: _doc
body: { foo: bar }

- match: { _index: "index" }
- match: { _type: "_doc" }
- match: { _version: 1}
- set: { _id: id }

- do:
get: # using typeful API on purpose
index: index
type: not_doc
id: '$id'

- match: { _index: "index" }
- match: { _type: "not_doc" } # the important bit to check
- match: { _id: $id}
- match: { _version: 1}
- match: { _source: { foo: bar }}

---
"Index call that introduces new field mappings":

- skip:
version: " - 6.6.99"
reason: Typeless APIs were introduced in 6.7.0

- do:
indices.create: # not using include_type_name: false on purpose
include_type_name: true
index: index
body:
mappings:
not_doc:
properties:
foo:
type: "keyword"
- do:
index:
index: index
type: _doc
id: 2
body: { new_field: value }

- match: { _index: "index" }
- match: { _type: "_doc" }
- match: { _id: "2" }
- match: { _version: 1 }

- do:
get: # using typeful API on purpose
index: index
type: not_doc
id: 2

- match: { _index: "index" }
- match: { _type: "not_doc" }
- match: { _id: "2" }
- match: { _version: 1}
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,22 @@
type: keyword

- do:
catch: /the final mapping would have more than 1 type/
index:
index: test-1
type: _doc
body: { bar: 42 }

# This cluster health call guarantees that changes are visible to the get-mappings API
- do:
cluster.health:
wait_for_events: normal

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

- is_true: test-1.mappings.my_type # the template is honored
- 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
@@ -0,0 +1,88 @@
---
"Update with typeless API on an index that has types":

- skip:
version: " - 6.6.99"
reason: Typeless APIs were introduced in 6.7.0

- do:
indices.create: # not using include_type_name: false on purpose
include_type_name: true
index: index
body:
mappings:
not_doc:
properties:
foo:
type: "keyword"

- do:
index:
index: index
type: not_doc
id: 1
body: { foo: bar }

- do:
update:
index: index
type: _doc
id: 1
body:
doc:
foo: baz

- do:
get:
index: index
type: not_doc
id: 1

- match: { _source.foo: baz }

---
"Update call that introduces new field mappings":

- skip:
version: " - 6.7.99"
reason: Typeless APIs were introduced in 6.7.0

- do:
indices.create: # not using include_type_name: false on purpose
include_type_name: true
index: index
body:
mappings:
not_doc:
properties:
foo:
type: "keyword"

- do:
index:
index: index
type: not_doc
id: 1
body: { foo: bar }

- do:
update:
index: index
type: _doc
id: 1
body:
doc:
foo: baz
new_field: value
- do:
get: # using typeful API on purpose
index: index
type: not_doc
id: 1

- match: { _index: "index" }
- match: { _type: "not_doc" }
- match: { _id: "1" }
- match: { _version: 2}
- match: { _source.foo: baz }
- match: { _source.new_field: value }
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ protected void doRun() throws Exception {
case INDEX:
IndexRequest indexRequest = (IndexRequest) docWriteRequest;
final IndexMetaData indexMetaData = metaData.index(concreteIndex);
MappingMetaData mappingMd = indexMetaData.mappingOrDefault(indexRequest.type());
MappingMetaData mappingMd = indexMetaData.mappingOrDefault(
indexMetaData.resolveDocumentType(indexRequest.type()));
Version indexCreated = indexMetaData.getCreationVersion();
indexRequest.resolveRouting(metaData);
indexRequest.process(indexCreated, mappingMd, concreteIndex.getName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ static void executeBulkItemRequest(BulkPrimaryExecutionContext context, UpdateHe
case UPDATED:
IndexRequest indexRequest = updateResult.action();
IndexMetaData metaData = context.getPrimary().indexSettings().getIndexMetaData();
MappingMetaData mappingMd = metaData.mappingOrDefault(indexRequest.type());
MappingMetaData mappingMd = metaData.mappingOrDefault(metaData.resolveDocumentType(indexRequest.type()));
indexRequest.process(metaData.getCreationVersion(), mappingMd, updateRequest.concreteIndex());
context.setRequestToExecute(indexRequest);
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,29 @@ public MappingMetaData mappingOrDefault(String mappingType) {
return mappings.get(MapperService.DEFAULT_MAPPING);
}

/**
* Resolves a type from a mapping-related request into the type that should be used when
* merging and updating mappings.
*
* If the special `_doc` type is provided, then we replace it with the actual type that is
* being used in the mappings. This allows typeless APIs such as 'index' or 'put mappings'
* to work against indices with a custom type name.
*/
public String resolveDocumentType(String type) {
if (MapperService.SINGLE_MAPPING_NAME.equals(type) &&
mappings.containsKey(type) == false &&
getCreationVersion().onOrAfter(Version.V_6_0_0)) {
// If the type is _doc and we have a 6.x index, then _doc is an alias
// for the actual type of the index (if any)
for (ObjectCursor<String> cursor : mappings.keys()) {
if (cursor.value.equals(MapperService.DEFAULT_MAPPING) == false) {
return cursor.value;
}
}
}
return type;
}

ImmutableOpenMap<String, DiffableStringMap> getCustomData() {
return this.customData;
}
Expand Down
Loading

0 comments on commit f14405a

Please sign in to comment.