Search code examples
python-2.7elasticsearchelasticsearch-py

How do I filter by geo-distance in elasticsearch-py?


Using Python 2.7 and elasticsearch-py.

Given the following JSON:

[
    {
        "Name":
        "Addresses": [
            "StreetAdd": "xxx",
            "GeoLocation": {
                "lat": xx,
                "long": yy
            }
        ]
    },
    {
        // And so on.
    }   
]

And the following mapping:

mapping = {
    "mappings": {
        "leads": {
            "properties": {
                "Addresses": {
                    "type": "nested",
                    "include_in_parent": "true",
                    "properties": {
                        "GeoLocation": "geo_point"
                    }
                }
            }
        }
    }
}

How would I get the locations within 10km of latitude 40, longitude -70? My attempt is as follows:

search_body = {
    "query" : { 
        "filtered": {
            "query": {
                "match_all" : { }
            },
            "filter": {
                "geo_distance": {
                    "distance": "10km",
                    "Addresses.GeoLocation": {
                        "lat": 40.0,
                        "lon": -70.0
                    }
                }
            }
        }
    },
    "size": 50
}

result = es.search(index=ES_INDEX, body=search_body, sort="Name:asc")
for hit in result["hits"]["hits"]:
    print hit["_source"]["Name"]

However, this is throwing the following error:

...
C:\Users\xxx\AppData\Local\Continuum\Anaconda2\lib\site-packages\elasticsearch\connection\base.pyc in _raise_error(self, status_code, raw_data)
    103             pass
    104 
--> 105         raise HTTP_EXCEPTIONS.get(status_code, TransportError)(status_code, error_message, additional_info)
    106 
    107 

RequestError: TransportError(400, u'search_phase_execution_exception')

Not that proficient yet with ES, so I'm having a hard time envisioning what schema I should use to approach this problem.

What gives?


Solution

  • The issue is in your mapping. Here is the fixed version

    mapping = {
        "mappings": {
            "leads": {
                "properties": {
                    "Addresses": {
                        "type": "nested",
                        "include_in_parent": "true",
                        "properties": {
                            "GeoLocation": {
                                "type":"geo_point" <-- Note the type here
                            }
                        }
                    }
                }
            }
        }
    }