diff --git a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/110_composite.yml b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/110_composite.yml index 2c80545050bd8..dad3ce22e945f 100644 --- a/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/110_composite.yml +++ b/modules/runtime-fields-common/src/yamlRestTest/resources/rest-api-spec/test/runtime_fields/110_composite.yml @@ -102,3 +102,19 @@ query: - match: {aggregations.response.buckets.0.doc_count: 5 } - match: {aggregations.response.buckets.1.key: 304 } - match: {aggregations.response.buckets.1.doc_count: 1 } + +--- +"Field caps with composite runtime mappings section. Issue 76742": + + - skip: + version: " - 7.14.99" + reason: Composite Runtime mappings support was added in 7.15 + + - do: + field_caps: + index: http_logs + fields: "*" + + - match: {indices: ["http_logs"]} + - match: {fields.http\.response.long.type: long} + - match: {fields.http\.clientip.ip.type: ip} diff --git a/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesIndexAction.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesIndexAction.java index 369a65be9e3bb..46d8b21f7c5fe 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesIndexAction.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesIndexAction.java @@ -140,10 +140,13 @@ private FieldCapabilitiesIndexResponse shardOperation(final FieldCapabilitiesInd if (searchExecutionContext.getFieldType(parentField) == null) { // no field type, it must be an object field ObjectMapper mapper = searchExecutionContext.getObjectMapper(parentField); - String type = mapper.isNested() ? "nested" : "object"; - IndexFieldCapabilities fieldCap = new IndexFieldCapabilities(parentField, type, - false, false, false, Collections.emptyMap()); - responseMap.put(parentField, fieldCap); + // Composite runtime fields do not have a mapped type for the root - check for null + if (mapper != null) { + String type = mapper.isNested() ? "nested" : "object"; + IndexFieldCapabilities fieldCap = new IndexFieldCapabilities(parentField, type, + false, false, false, Collections.emptyMap()); + responseMap.put(parentField, fieldCap); + } } dotIndex = parentField.lastIndexOf('.'); } diff --git a/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java b/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java index e8ebe13280ebf..7437c55cf6894 100644 --- a/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java +++ b/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java @@ -30,6 +30,7 @@ import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.core.Nullable; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.IndexSortConfig; @@ -383,6 +384,12 @@ private MappedFieldType fieldType(String name) { return fieldType == null ? mappingLookup.getFieldType(name) : fieldType; } + /** + * + * @param name name of the object + * @return can be null e.g. if field is root of a composite runtime field + */ + @Nullable public ObjectMapper getObjectMapper(String name) { return mappingLookup.objectMappers().get(name); }