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/TransportFieldCapabilitiesAction.java b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java index 73782e12c929f..3f39d47613002 100644 --- a/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java +++ b/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java @@ -371,10 +371,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, + // 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); + 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 dc3b3bf84f920..590a34d5fb820 100644 --- a/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java +++ b/server/src/main/java/org/elasticsearch/index/query/SearchExecutionContext.java @@ -27,6 +27,7 @@ import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.core.CheckedFunction; +import org.elasticsearch.core.Nullable; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.IndexSortConfig; @@ -365,6 +366,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); }