Przeglądaj źródła

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.
Alexander Reelsen 11 lat temu
rodzic
commit
a3abcdc93a

+ 1 - 1
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",

+ 18 - 7
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}
+

+ 88 - 16
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.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.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}
+  - 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}
+

+ 2 - 0
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<String, ImmutableMap<String, ImmutableMap<String, FieldMappingMetaData>>> indexEntry : mappings.entrySet()) {
             builder.startObject(indexEntry.getKey(), XContentBuilder.FieldCaseConversion.NONE);
+            builder.startObject("mappings");
             for (Map.Entry<String, ImmutableMap<String, FieldMappingMetaData>> typeEntry : indexEntry.getValue().entrySet()) {
                 builder.startObject(typeEntry.getKey(), XContentBuilder.FieldCaseConversion.NONE);
                 for (Map.Entry<String, FieldMappingMetaData> fieldEntry : typeEntry.getValue().entrySet()) {
@@ -81,6 +82,7 @@ public class GetFieldMappingsResponse extends ActionResponse implements ToXConte
                 builder.endObject();
             }
             builder.endObject();
+            builder.endObject();
         }
         return builder;
     }

+ 3 - 2
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()));