Q:

Restrict aggregation to results of filter

Given a set of documents that have a given value in one field, I want to know how many documents there are that have each value for a second field.
I've tried to do that with a terms aggregation with the following query:
{
    "size": 0,
    "filter": {
        "term": {
            "field1": "value"
        }
    },
    "aggregations": {
        "field2" : {
            "terms" : { "field" : "field2" }
        }
    }
}

but the returned counts show the number of documents with each value for the second field in the whole index, and not restricted to those documents with a given value for the first field.
What am I doing wrong?

A:

Have you tried using filtered query?
{
    "query": {
        "filtered": {
           "query": {
                "match_all": {}
           },
           "filter": {
               "term": {
                  "field1": "value"
               }
           }
        }
    },
    "aggregations": {
        "field2": {
           "terms": { "field": "field2" }
        }
    }
}

A:

There is a comparison here:
https://www.elastic.co/guide/en/elasticsearch/guide/current/_post_filter.html
In short, your top-level filter is acting like a post_filter in the link. To filter, then compute the aggregate, you need to use a query.
If you are concerned about the performance hit because of the computation of scores in queries, you can look into constant score queries which basically a filter-wrapper query.

