Search code examples
elasticsearchfiltergeolocation

Elasticsearch query for values that exist in multiple geo locations


I have an index with documents that look like the following:

{
    "name": "some name",
    "location: { "type": "Point", "coordinates": [3.295, 6.673]}
}

I can do a geo-polygon query no problem. But now I want to search two geo-polygons and have it return only those documents that have the same "name" value in both. So if "name":"Jason Smith" exists in both geo-polygons, then those documents will be returned. But if "Jason Smith" only exists in one, then it will not be returned. I can't figure out how to write this query, so any help would be greatly appreciated.

Here is the query I am working with now:

{
    "query":{
        "bool":{
            "filter":{
                "bool":{
                    "should":[
                        {"geo_distance": {"coordinates":[32.4809, 12.0422],"distance": "100 m"}},
                        {"geo_distance": {"coordinates":[33.4827, 13.0438],"distance": "100 m"}}
                    ]
                }
            }
        }
    },
    "aggs":{
        "found":{
            "terms":{
                "field": "name"
            }
        }
    }
}

I've tried both "must" and "should". Must will only return documents that have a lat/lng coordinate in both areas, and Should returns all documents from both areas. I need the query to return documents that have the same "name" in both areas, not coordinate.


Solution

  • Ok so i edited. Should work we agg by name, then by zone using one of the aera requested. After we post filter aggregation using bucket_selector, _bucket_count gets the array size of the subaggeo aggregates, and so if his size is == 2, name is on both aera. Please tell me if it s work ;)

    {
      "query": {
        "bool": {
          "filter": {
            "bool": {
              "should": [
                {
                  "geo_distance": {
                    "coordinates": {
                      "lat": 48.858837,
                      "lon": 2.27702
                    },
                    "distance": "10km"
                  }
                },
                {
                  "geo_distance": {
                    "coordinates": {
                      "lat": 40.697149,
                      "lon": -74.2598
                    },
                    "distance": "10km"
                  }
                }
              ]
            }
          }
        }
      },
      "aggs": {
        "found": {
          "terms": {
            "field": "name",
            "min_doc_count": 2
          },
          "aggs": {
            "subagggeo": {
              "geo_distance": {
                "field": "coordinates",
                "origin": "48.858837, 2.27702",
                "unit": "m",
                "ranges": [
                  {
                    "to": 10000
                  },
                  {
                    "from": 10001
                  }
                ]
              }
            },
            "min_bucket_selector": {
          "bucket_selector": {
            "buckets_path": {
              "hits": "subagggeo._bucket_count"
            },
            "script": {
              "inline": "params.hits > 1"
            }
          }
        }
          }
        }
      }
    }