From a3abcdc93a004bea53ba2d4cbab585f8820b660d Mon Sep 17 00:00:00 2001 From: Alexander Reelsen Date: Tue, 14 Jan 2014 22:39:28 +0100 Subject: [PATCH] Consistent APIs: Get field mapping API includes 'mappings' The get field mapping API now includes a mappings element after the index in its JSON Added more consistent endpoint /{index}/_mapping/{type}/field/{fields} and added endpoint /_mapping/{type}/field/{fields} which are also used in tests Added rest spec tests for wildcards and _all Relates #4071 NOTE: This is not yet complete for 1.0. We need to return an empty JSON document instead of a 404 if the field of an existing index and type is not found. However this is not possible with the current data structure being returned. Needs to be finished for 1.0. --- .../api/indices.get_field_mapping.json | 2 +- .../indices.get_field_mapping/10_basic.yaml | 25 +++-- .../50_field_wildcards.yaml | 104 +++++++++++++++--- .../mapping/get/GetFieldMappingsResponse.java | 2 + .../get/RestGetFieldMappingAction.java | 5 +- 5 files changed, 112 insertions(+), 26 deletions(-) diff --git a/rest-api-spec/api/indices.get_field_mapping.json b/rest-api-spec/api/indices.get_field_mapping.json index b683bf4ee0c..1d823e23104 100644 --- a/rest-api-spec/api/indices.get_field_mapping.json +++ b/rest-api-spec/api/indices.get_field_mapping.json @@ -4,7 +4,7 @@ "methods": ["GET"], "url": { "path": "/_mapping/field/{field}", - "paths": ["/_mapping/field/{field}", "/{index}/_mapping/field/{field}", "/{index}/{type}/_mapping/field/{field}"], + "paths": ["/_mapping/field/{field}", "/{index}/_mapping/field/{field}", "/_mapping/{type}/field/{field}", "/{index}/_mapping/{type}/field/{field}"], "parts": { "index": { "type" : "list", diff --git a/rest-api-spec/test/indices.get_field_mapping/10_basic.yaml b/rest-api-spec/test/indices.get_field_mapping/10_basic.yaml index 4d4614629c2..bac6fffc0a5 100644 --- a/rest-api-spec/test/indices.get_field_mapping/10_basic.yaml +++ b/rest-api-spec/test/indices.get_field_mapping/10_basic.yaml @@ -17,7 +17,7 @@ setup: indices.get_field_mapping: field: text - - match: {test_index.test_type.text.mapping.text.type: string} + - match: {test_index.mappings.test_type.text.mapping.text.type: string} --- "Get field mapping by index only": @@ -26,7 +26,7 @@ setup: index: test_index field: text - - match: {test_index.test_type.text.mapping.text.type: string} + - match: {test_index.mappings.test_type.text.mapping.text.type: string} --- "Get field mapping by type & field": @@ -37,7 +37,7 @@ setup: type: test_type field: text - - match: {test_index.test_type.text.mapping.text.type: string} + - match: {test_index.mappings.test_type.text.mapping.text.type: string} --- "Get field mapping by type & field, with another field that doesn't exist": @@ -48,8 +48,8 @@ setup: type: test_type field: [ text , text1 ] - - match: {test_index.test_type.text.mapping.text.type: string} - - is_false: test_index.test_type.text1 + - match: {test_index.mappings.test_type.text.mapping.text.type: string} + - is_false: test_index.mappings.test_type.text1 --- "Get field mapping with include_defaults": @@ -61,5 +61,16 @@ setup: field: text include_defaults: true - - match: {test_index.test_type.text.mapping.text.type: string} - - match: {test_index.test_type.text.mapping.text.analyzer: default} + - match: {test_index.mappings.test_type.text.mapping.text.type: string} + - match: {test_index.mappings.test_type.text.mapping.text.analyzer: default} + +--- +"Get field mapping should work without index specifying type and field": + + - do: + indices.get_field_mapping: + type: test_type + field: text + + - match: {test_index.mappings.test_type.text.mapping.text.type: string} + diff --git a/rest-api-spec/test/indices.get_field_mapping/50_field_wildcards.yaml b/rest-api-spec/test/indices.get_field_mapping/50_field_wildcards.yaml index 879d74988f5..fcf59263266 100644 --- a/rest-api-spec/test/indices.get_field_mapping/50_field_wildcards.yaml +++ b/rest-api-spec/test/indices.get_field_mapping/50_field_wildcards.yaml @@ -23,6 +23,29 @@ setup: type: string index_name: t3 + - do: + indices.create: + index: test_index_2 + body: + mappings: + test_type_2: + properties: + t1: + type: string + t2: + type: string + obj: + path: just_name + properties: + t1: + type: string + i_t1: + type: string + index_name: t1 + i_t3: + type: string + index_name: t3 + --- "Get field mapping with * for fields": @@ -30,43 +53,92 @@ setup: indices.get_field_mapping: field: "*" - - match: {test_index.test_type.t1.full_name: t1 } - - match: {test_index.test_type.t2.full_name: t2 } - - match: {test_index.test_type.obj\.t1.full_name: obj.t1 } - - match: {test_index.test_type.obj\.i_t1.full_name: obj.i_t1 } - - match: {test_index.test_type.obj\.i_t3.full_name: obj.i_t3 } + - match: {test_index.mappings.test_type.t1.full_name: t1 } + - match: {test_index.mappings.test_type.t2.full_name: t2 } + - match: {test_index.mappings.test_type.obj\.t1.full_name: obj.t1 } + - match: {test_index.mappings.test_type.obj\.i_t1.full_name: obj.i_t1 } + - match: {test_index.mappings.test_type.obj\.i_t3.full_name: obj.i_t3 } --- "Get field mapping with t* for fields": - do: indices.get_field_mapping: + index: test_index field: "t*" # i_t1 matches the pattern using it's index name, but t1 already means a full name # of a field and thus takes precedence. - - match: {test_index.test_type.t1.full_name: t1 } - - match: {test_index.test_type.t2.full_name: t2 } - - match: {test_index.test_type.t3.full_name: obj.i_t3 } - - length: {test_index.test_type: 3} + - match: {test_index.mappings.test_type.t1.full_name: t1 } + - match: {test_index.mappings.test_type.t2.full_name: t2 } + - match: {test_index.mappings.test_type.t3.full_name: obj.i_t3 } + - length: {test_index.mappings.test_type: 3} --- "Get field mapping with *t1 for fields": - do: indices.get_field_mapping: + index: test_index field: "*t1" - - match: {test_index.test_type.t1.full_name: t1 } - - match: {test_index.test_type.obj\.t1.full_name: obj.t1 } - - match: {test_index.test_type.obj\.i_t1.full_name: obj.i_t1 } - - length: {test_index.test_type: 3} + - match: {test_index.mappings.test_type.t1.full_name: t1 } + - match: {test_index.mappings.test_type.obj\.t1.full_name: obj.t1 } + - match: {test_index.mappings.test_type.obj\.i_t1.full_name: obj.i_t1 } + - length: {test_index.mappings.test_type: 3} --- "Get field mapping with wildcarded relative names": - do: indices.get_field_mapping: + index: test_index field: "i_*" - - match: {test_index.test_type.i_t1.full_name: obj.i_t1 } - - match: {test_index.test_type.i_t3.full_name: obj.i_t3 } - - length: {test_index.test_type: 2} + - match: {test_index.mappings.test_type.i_t1.full_name: obj.i_t1 } + - match: {test_index.mappings.test_type.i_t3.full_name: obj.i_t3 } + - length: {test_index.mappings.test_type: 2} + +--- +"Get field mapping should work using '_all' for indices and types": + + - do: + indices.get_field_mapping: + index: _all + type: _all + field: "i_*" + - match: {test_index.mappings.test_type.i_t1.full_name: obj.i_t1 } + - match: {test_index.mappings.test_type.i_t3.full_name: obj.i_t3 } + - length: {test_index.mappings.test_type: 2} + - match: {test_index_2.mappings.test_type_2.i_t1.full_name: obj.i_t1 } + - match: {test_index_2.mappings.test_type_2.i_t3.full_name: obj.i_t3 } + - length: {test_index_2.mappings.test_type_2: 2} + +--- +"Get field mapping should work using '*' for indices and types": + + - do: + indices.get_field_mapping: + index: '*' + type: '*' + field: "i_*" + - match: {test_index.mappings.test_type.i_t1.full_name: obj.i_t1 } + - match: {test_index.mappings.test_type.i_t3.full_name: obj.i_t3 } + - length: {test_index.mappings.test_type: 2} + - match: {test_index_2.mappings.test_type_2.i_t1.full_name: obj.i_t1 } + - match: {test_index_2.mappings.test_type_2.i_t3.full_name: obj.i_t3 } + - length: {test_index_2.mappings.test_type_2: 2} + +--- +"Get field mapping should work using comma_separated values for indices and types": + + - do: + indices.get_field_mapping: + index: 'test_index,test_index_2' + type: 'test_type,test_type_2' + field: "i_*" + - match: {test_index.mappings.test_type.i_t1.full_name: obj.i_t1 } + - match: {test_index.mappings.test_type.i_t3.full_name: obj.i_t3 } + - length: {test_index.mappings.test_type: 2} + - match: {test_index_2.mappings.test_type_2.i_t1.full_name: obj.i_t1 } + - match: {test_index_2.mappings.test_type_2.i_t3.full_name: obj.i_t3 } + - length: {test_index_2.mappings.test_type_2: 2} + diff --git a/src/main/java/org/elasticsearch/action/admin/indices/mapping/get/GetFieldMappingsResponse.java b/src/main/java/org/elasticsearch/action/admin/indices/mapping/get/GetFieldMappingsResponse.java index da612f602d9..a62ea0d353b 100644 --- a/src/main/java/org/elasticsearch/action/admin/indices/mapping/get/GetFieldMappingsResponse.java +++ b/src/main/java/org/elasticsearch/action/admin/indices/mapping/get/GetFieldMappingsResponse.java @@ -71,6 +71,7 @@ public class GetFieldMappingsResponse extends ActionResponse implements ToXConte public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { for (Map.Entry>> indexEntry : mappings.entrySet()) { builder.startObject(indexEntry.getKey(), XContentBuilder.FieldCaseConversion.NONE); + builder.startObject("mappings"); for (Map.Entry> typeEntry : indexEntry.getValue().entrySet()) { builder.startObject(typeEntry.getKey(), XContentBuilder.FieldCaseConversion.NONE); for (Map.Entry fieldEntry : typeEntry.getValue().entrySet()) { @@ -81,6 +82,7 @@ public class GetFieldMappingsResponse extends ActionResponse implements ToXConte builder.endObject(); } builder.endObject(); + builder.endObject(); } return builder; } diff --git a/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/get/RestGetFieldMappingAction.java b/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/get/RestGetFieldMappingAction.java index 946f29a7e40..269098d0a87 100644 --- a/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/get/RestGetFieldMappingAction.java +++ b/src/main/java/org/elasticsearch/rest/action/admin/indices/mapping/get/RestGetFieldMappingAction.java @@ -49,17 +49,18 @@ public class RestGetFieldMappingAction extends BaseRestHandler { public RestGetFieldMappingAction(Settings settings, Client client, RestController controller) { super(settings, client); controller.registerHandler(GET, "/_mapping/field/{fields}", this); + controller.registerHandler(GET, "/_mapping/{type}/field/{fields}", this); controller.registerHandler(GET, "/{index}/_mapping/field/{fields}", this); controller.registerHandler(GET, "/{index}/{type}/_mapping/field/{fields}", this); + controller.registerHandler(GET, "/{index}/_mapping/{type}/field/{fields}", this); } @Override public void handleRequest(final RestRequest request, final RestChannel channel) { final String[] indices = Strings.splitStringByCommaToArray(request.param("index")); - final String[] types = Strings.splitStringByCommaToArray(request.param("type")); + final String[] types = request.paramAsStringArrayOrEmptyIfAll("type"); boolean local = request.paramAsBooleanOptional("local", false); final String[] fields = Strings.splitStringByCommaToArray(request.param("fields")); - GetFieldMappingsRequest getMappingsRequest = new GetFieldMappingsRequest(); getMappingsRequest.indices(indices).types(types).local(local).fields(fields).includeDefaults(request.paramAsBoolean("include_defaults", false)); getMappingsRequest.indicesOptions(IndicesOptions.fromRequest(request, getMappingsRequest.indicesOptions()));