Search code examples
elasticsearchelasticsearch-aggregationelasticsearch-dslaws-elasticsearch

How to perform aggregation (eg. avg) on list of objects in Elasticsearch?


I have data in the following form in Elasticsearch:

[
    {
        "id": 1,
        "name": "abc",
        "score": 10,
        "values": [
            {
                "v1": 1,
                "v2": 2
            }
        ]
    },
    {
        "id": 2,
        "name": "def",
        "score": 20,
        "values": [
            {
                "v1": 3,
                "v2": 4
            }
        ]
    }
]

Currently, I am calculating average on score using the following code:

s = Search(using=es, index=index).query(Q(query))
s.aggs.bucket('average_score', 'avg', field='score') # average_score = 15

Now I wish to compute average on v1 and v2 using elasticsearch_dsl but I don't know how to do nested aggregation. In this example, v1 = 2 and v2 = 3. Please help. Thanks in advance!

Edit: Unfortunately, here values is an object instead of nested.


Solution

  • No idea how to do it in your DSL but here are the raw steps.


    Mapping:

    PUT avgs/
    {
      "mappings": {
        "properties": {
          "values": {
            "type": "nested",
            "properties": {
              "v1": {
                "type": "integer"
              },
              "v2": {
                "type": "integer"
              }
            }
          }
        }
      }
    }
    

    Indexing:

    POST avgs/_doc
    {
      "id": 1,
      "name": "abc",
      "score": 10,
      "values": [
        {
          "v1": 1,
          "v2": 2
        }
      ]
    }
    
    POST avgs/_doc
    {
      "id": 2,
      "name": "def",
      "score": 20,
      "values": [
        {
          "v1": 3,
          "v2": 4
        }
      ]
    }
    

    Querying:

    GET avgs/_search
    {
      "size": 0,
      "aggs": {
        "avg_v1": {
          "nested": {
            "path": "values"
          },
          "aggs": {
            "nested_v1": {
              "avg": {
                "field": "values.v1"
              }
            }
          }
        },
        "avg_v2": {
          "nested": {
            "path": "values"
          },
          "aggs": {
            "nested_v2": {
              "avg": {
                "field": "values.v2"
              }
            }
          }
        }
      }
    }
    

    Yielding:

    ...
      "aggregations" : {
        "avg_v2" : {
          "doc_count" : 2,
          "nested_v2" : {
            "value" : 3.0
          }
        },
        "avg_v1" : {
          "doc_count" : 2,
          "nested_v1" : {
            "value" : 2.0
          }
        }
      }
    ...