Geo encoding a location Part 2

Project source code: https://github.com/antp/locations

Project demo

This project will use OpenStreetMap Nominatim service to GEO encode addresses and OpenStreetMap via Leaflet.js to display multiple independent maps on a single.

It is always good to see a demonstration of the example project...

project demonstration GIF

Creating the project

Create a Phoenix application, in this example, called locations with:

> mix phx.new locations —binary_id —live

The next step is to add geo_postgis to the project, to enable the use of GIS functionality. This will allow queries to be run that will, for example, find all locations in the database within 50Km of an address.

Add geo_postgis. Full installation and configuration instructions can be found there, but in short:

Add it to your mix file.

{:geo_postgis, "~> 3.0"}

And run to get the dependency:

> mix reps.get

Add a migration called add postgis with the following contents:

defmodule Location.Repo.Migrations.AddPostgis do
  use Ecto.Migration

  def up do
    execute "CREATE EXTENSION IF NOT EXISTS postgis"
  end

  def down do
    execute "DROP EXTENSION IF EXISTS postgis"
  end
end

Then create a migration for the location table:

defmodule Location.Repo.Migrations.AddLocation do
  use Ecto.Migration

  def change do
    create table(:locations, primary_key: false) do
      add :id, :binary_id, primary_key: true

      add :addr1, :string, null: false
      add :addr2, :string, null: true
      add :city, :string, null: false
      add :county, :string, null: true
      add :postcode, :string, null: false
      add :country, :string, null: false

      add :geo_error, :binary, null: true
      add :geo_selected_id, :int8, null: true
      add :geo_features, :jsonb, null: true
      add :lat, :float, null: true
      add :lon, :float, null: true
      add :geolocation, :geometry, null: true

      timestamps()
    end
  end
end

This will create the locations table. A location has two parts, the address and the geographical information.

In order to display a location symbol on a map, the latitude and longitude of the location must be known. This information is contained in the lat and lon fields above. This information is also encoded in the geographical field geolocation. This field will be used in the GIS queries.

The features returned from locating an address are held in geo_features. It is possible for an address to encode to several points, so there may be more than one feature. The geo_selected_id contains the osm_id of the currently selected feature by the user.

In the case of errors geo_error will contain the error information.

Create the database and tables with:

>mix ecto.reset

The initial application and database is now setup.

Next: Encoding an address.