Search code examples
searchelasticsearchsearch-engine

Elasticsearch aggregate by geo location


I want to group data by their location with shapes and bounding boxes. For example group the results by hemisphere:

GET cdc/_search
{
   "from": 0,
   "size": 0,
   "query": {
      "match_all": {}
   },
   "aggs": {
      "group_by_geo": {
         "geo_bounding_box": {
            "field": "location",
            "boxes": [
               {
                  "top_left": {
                     "lat": 90,
                     "lon": -180
                  },
                  "bottom_right": {
                     "lat": 0,
                     "lon": 0
                  }
               },
               {
                  "top_left": {
                     "lat": 90,
                     "lon": 0
                  },
                  "bottom_right": {
                     "lat": 0,
                     "lon": 180
                  }
               },
               {
                  "top_left": {
                     "lat": 0,
                     "lon": -180
                  },
                  "bottom_right": {
                     "lat": -90,
                     "lon": 0
                  }
               },
               {
                  "top_left": {
                     "lat": 0,
                     "lon": 0
                  },
                  "bottom_right": {
                     "lat": -90,
                     "lon": 180
                  }
               }
            ]
         },
         "aggs": {
            "over_time": {
               "date_histogram": {
                  "field": "date",
                  "interval": "day",
                  "format": "yyyy-MM-dd"
               },
               "aggs": {
                  "AvgTemp": {
                     "avg": {
                        "field": "hits"
                     }
                  }
               }
            }
         }
      }
   }
}

So the over_timepart works fine isolated but this query gives me "reason": "Could not find aggregator type [geo_bounding_box] in [group_by_geo]"

My syntax is inspired by range aggregations but apparently this is not working in this case.

Is this possible or do I have to make separate queries filtering by the 4 boxes?


Solution

  • There's no geo_bounding_box aggregation, (there's a geo_bounding_box filter, though).

    You can achieve what you need using a filters aggregation containing one geo_bounding_box filter for each bounding box. Basically something like this:

    {
      "from": 0,
      "size": 0,
      "query": {
        "match_all": {}
      },
      "aggs": {
        "group_by_geo": {
          "filters": {
            "filters": {
              "box1": {
                "geo_bounding_box": {
                  "location": {
                    "top_left": {
                      "lat": 90,
                      "lon": -180
                    },
                    "bottom_right": {
                      "lat": 0,
                      "lon": 0
                    }
                  }
                }
              },
              "box2": {
                "geo_bounding_box": {
                  "location": {
                    "top_left": {
                      "lat": 90,
                      "lon": 0
                    },
                    "bottom_right": {
                      "lat": 0,
                      "lon": 180
                    }
                  }
                }
              },
              "box3": {
                "geo_bounding_box": {
                  "location": {
                    "top_left": {
                      "lat": 0,
                      "lon": -180
                    },
                    "bottom_right": {
                      "lat": -90,
                      "lon": 0
                    }
                  }
                }
              },
              "box4": {
                "geo_bounding_box": {
                  "location": {
                    "top_left": {
                      "lat": 0,
                      "lon": 0
                    },
                    "bottom_right": {
                      "lat": -90,
                      "lon": 180
                    }
                  }
                }
              }
            }
          },
          "aggs": {
            "over_time": {
              "date_histogram": {
                "field": "date",
                "interval": "day",
                "format": "yyyy-MM-dd"
              },
              "aggs": {
                "AvgTemp": {
                  "avg": {
                    "field": "hits"
                  }
                }
              }
            }
          }
        }
      }
    }