Search code examples
elasticsearchelasticsearch-aggregationelasticsearch-dsl

How Elasticsearch do filter aggregation


I need to do average aggregation, but I want to filter some values. In the below examples, I want filter the length=100, so I want to do average for length (with doc #1 and doc #2) and for width with all documents. So I expect to see length average as 9 and width average as 5. What should I do?

document example:

["id": 1, "length": 10, "width":8]
["id": 2, "length": 8, "width":2]
["id": 3, "length": 100, "width":5]

And In some other case, length may not exist, How about this case?

["id": 1, "length": 10, "width":8]
["id": 2, "length": 8, "width":2]
["id": 3, "width":5]
termAggregation.subAggregation(AggregationBuilders.avg("length").field("length"))
.subAggregation(AggregationBuilders.avg("width").field("width"));

Solution

  • Your aggregation query will look like below for excluding 100 from aggregation. You need to use filter aggregation and inside that avg as sub aggregation.

    {
      "size": 0,
      "aggs": {
        "cal": {
          "filter": {
            "bool": {
              "must_not": [
                {
                  "match": {
                    "length": "100"
                  }
                }
              ]
            }
          },
          "aggs": {
            "avg_length": {
              "avg": {
                "field": "length"
              }
            }
          }
        },
        "avg_width":{
          "avg": {
            "field": "width"
          }
        }
      }
    }
    

    Java code

    AvgAggregationBuilder widthAgg = new AvgAggregationBuilder("avg_width").field("width");
            AvgAggregationBuilder lengthAgg = new AvgAggregationBuilder("avg_length").field("length");
    
            FilterAggregationBuilder filter = new FilterAggregationBuilder("cal",
                    QueryBuilders.boolQuery().mustNot(QueryBuilders.matchQuery("length", "100")));
            filter.subAggregation(lengthAgg);
            
            SearchSourceBuilder ssb = new SearchSourceBuilder();
            ssb.aggregation(filter);
            ssb.aggregation(widthAgg);
            
            System.out.println(ssb.toString());
    

    Response

    "aggregations": {
        "avg_width": {
          "value": 5
        },
        "cal": {
          "meta": {},
          "doc_count": 3,
          "avg_length": {
            "value": 9
          }
        }
      }