Geo encoding a location Part 1

  • Antony Pinchbeck
  • 2020-09-01
  • Elixir

I recently had the requirement to add map locations to a Phoenix liveview application.

The requirements meant that the lookup should be low volume and there will be a lot of duplication of locations. The duplication is handy as the results can be cached and used for future lookups.

Selecting a provider

I looked at several of the geo location providers. Because the requirements are for a low volume and there will be a lot of duplication I opted for OpenStreetMaps nominatim service.

This has the bonus of being free, but do keep in mind their usage policy.

  1. No bulk encoding
  2. Limit requests to one a second

Encoding a location

OpenStreetMap provides a debugging interface to explore their lookup service.

They also provide the API documentation.

First experiments

Typing “Ashmolean Museum, Beaumont St, Oxford OX1 2PH” into the search box will show a map with the Ashmolean outlined.

Looking at the URL bar shows the query format required for the lookup.

https://nominatim.openstreetmap.org/ui/search.html?q=Ashmolean+Museum%2C+Beaumont+St%2C+Oxford+OX1+2PH

This is using a ‘free form’ query, which will process the data from the left to right and if that fails to resolve, it will run it right to left.

Additionally, the documentation advises that commas (%2C) should be used to separate the different parts of the address to improve performance.

The API provides many different formats for the returned data, in this case geojson was selected because the data can easily be converted to an Elixir struct.

If the following query is run,

https://nominatim.openstreetmap.org/search?q=Ashmolean+Museum%2C+Beaumont+St%2C+Oxford%2C+OX1+2PH%2C+United+Kingdom&format=geojson&addressdetails=0

The following is returned, after conversion to Elixir

%{
   "features" => [
     %{
       "bbox" => [-1.2610599, 51.7550872, -1.2596908, 51.755894],
       "geometry" => %{
         "coordinates" => [-1.26025778822966, 51.755499],
         "type" => "Point"
       },
       "properties" => %{
         "category" => "tourism",
         "display_name" => "Ashmolean Museum, Beaumont Street, Jericho, Oxford, Oxfordshire, South East, England, OX1 2PH, United Kingdom",
         "icon" => "https://nominatim.openstreetmap.org/images/mapicons/tourist_museum.p.20.png",
         "importance" => 1.3996162545222703,
         "osm_id" => 1337584,
         "osm_type" => "relation",
         "place_id" => 235529572,
         "place_rank" => 30,
         "type" => "museum"
       },
       "type" => "Feature"
     }
   ],
   "licence" => "Data © OpenStreetMap contributors, ODbL 1.0. https://osm.org/copyright",
   "type" => "FeatureCollection"
 }

This has returned a single feature and gives the latitude and longitude information that is required to display a map in the geometry section. Also it provides the osm_id in the properties section. In the case of multiple features for a single location, this ID can be used to select the location that the user wants display the marker over from the features collection.

The osm_id should be used in preference to the place_id because the place_id is only unique within a nominatim server. Additionally the place_id may change when a server imports data.

Next: Creating the project

© 2001 - 2020 Component X Software Limited All rights reserved.

Lynx: 2.4.5