How to do two nested aggregations in elasticsearch?

katericata picture katericata · Nov 12, 2017 · Viewed 7.6k times · Source

City and home type are two nested objects in the following document mapping:

"mappings" : {
  "home_index_doc" : {
    "properties" : {
      "city" : {
        "type" : "nested",
        "properties" : {
          "country" : {
            "type" : "nested",
            "properties" : {
              "name" : {
                "type" : "text"
              }
            }
          },
          "name" : {
            "type" : "keyword"
          }
        }
      },
      "home_type" : {
        "type" : "nested",
        "properties" : {
          "name" : {
            "type" : "keyword"
          }
        }
      },
      ...
    }
  }
}

I am trying to do the following aggregation: Take all present documents and show all home_types per city.

I imagine it should look similar to:

"aggregations": {
  "all_cities": {
    "buckets": [
      {
        "key": "Tokyo",
         "doc_count": 12,
         "home_types": {
            "buckets": [
               {
                  "key": "apartment", 
                  "doc_count": 5
               },
               {
                  "key": "house",
                  "doc_count": 12
               }
            ]
         }
      },
      {
        "key": "New York",
         "doc_count": 1,
         "home_types": {
            "buckets": [
               {
                  "key": "house", 
                  "doc_count": 1
               }
            ]
         }
      }
    ]
  }
}

After trying gazzilion aproaches and combinations, I've made it that far with Kibana:

GET home-index/home_index_doc/_search
{
  "size": 0,
  "aggs": {
    "all_cities": {
     "nested": {
         "path": "city"
      },
      "aggs": {
        "city_name": {
          "terms": {
            "field": "city.name"
          }
        }
      }
    },
    "aggs": {
      "all_home_types": {
        "nested": {
          "path": "home_type"
        },
        "aggs": {
          "home_type_name": {
            "terms": {
              "field": "home_type.name"
            }
          }
        }
      }
    }
  }
}

and I get the following exception:

    "type": "unknown_named_object_exception",
    "reason": "Unknown BaseAggregationBuilder [all_home_types]",

Answer

Val picture Val · Nov 13, 2017

You need to use reverse_nested in order to jump out of the city nested type back at the root level and do another nested aggregation for the home_type nested type. Basically, like this:

{
  "size": 0,
  "aggs": {
    "all_cities": {
      "nested": {
        "path": "city"
      },
      "aggs": {
        "city_name": {
          "terms": {
            "field": "city.name"
          },
          "aggs": {
            "by_home_types": {
              "reverse_nested": {},
              "aggs": {
                "all_home_types": {
                  "nested": {
                    "path": "home_type"
                  },
                  "aggs": {
                    "home_type_name": {
                      "terms": {
                        "field": "home_type.name"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}