### Description

`TransportFieldCapabilitiesAction` (used for the the `_field_caps` endpoint) has got a nested loop in `merge` method when unmapped fields are included (https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java#L245). This loops over indices -> fields -> indices, which could cause an exponential blowup in objects used when there's a large number of indices and unmapped fields.

We could be more efficient in creating & sharing IndexCap objects in these situations.
server/src/main/java/org/elasticsearch/action/fieldcaps/FieldCapabilities.java
* The list of indices where this field is not aggregatable,
     * or null if the field is aggregatable in all indices.
     */
    public String[] nonAggregatableIndices() {
        return nonAggregatableIndices;
    }
    /**
     * The list of indices where this field has different dimension or metric flag
     */
    public String[] nonDimensionIndices() {
        return nonDimensionIndices;
    }
    /**
     * The list of indices where this field has different dimension or metric flag
     */
    public String[] metricConflictsIndices() {
        return metricConflictsIndices;
    }
    /**
     * Return merged metadata across indices.
     */
    public Map<String, Set<String>> meta() {
        return meta;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        FieldCapabilities that = (FieldCapabilities) o;
        return isMetadataField == that.isMetadataField