### Description

We have had this longstanding issue that running a top-level `filter` aggregation is often (not always, e.g. not if you need the total hit count too) a performance bug, as Elasticsearch would iterate over docs that match the `query` and would then check each of these docs against the filter of the `filter` aggregation. It's usually a better idea to put the filter directly into the query, where it can be used to drive iteration if appropriate.

We could do this automatically by implementing the `LeafCollector#competitiveIterator` API that was introduced for dynamic pruning, in order to automatically start intersecting the query with the filter of the `filter` aggregator once enough hits have been counted.
server/src/main/java/org/elasticsearch/search/aggregations/bucket/filter/FilterByFilterAggregator.java
import org.apache.lucene.search.Scorable;
import org.apache.lucene.util.Bits;
import org.elasticsearch.core.CheckedFunction;
import org.elasticsearch.search.aggregations.AdaptingAggregator;
import org.elasticsearch.search.aggregations.AggregationExecutionContext;
import org.elasticsearch.search.aggregations.Aggregator;
import org.elasticsearch.search.aggregations.AggregatorFactories;
import org.elasticsearch.search.aggregations.CardinalityUpperBound;
import org.elasticsearch.search.aggregations.LeafBucketCollector;
import org.elasticsearch.search.aggregations.support.AggregationContext;
import org.elasticsearch.search.runtime.AbstractScriptFieldQuery;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiConsumer;
/**
 * Collects results by running each filter against the searcher and doesn't
 * build any {@link LeafBucketCollector}s which is generally faster than
 * {@link Compatible} but doesn't support when there is a parent aggregator
 * or any child aggregators.
 */
public class FilterByFilterAggregator extends FiltersAggregator {
    /**
     * Builds {@link FilterByFilterAggregator} when the filters are valid and
     * it would be faster than a "native" aggregation implementation. The
     * interface is designed to allow easy construction of
     * {@link AdaptingAggregator}.
     */
    public abstract static class AdapterBuilder<T> {