GraphQL and geolocation on Postgres (PostGIS using Hasura)
A primer to building backends for location-aware applications using postgres and GraphQL
In this post, we are going to go over how you can use Postgresql and GraphQL to build location aware applications. We are going to go over a simple use case where we are building a GraphQL backend for an application which shows a list of landmarks around you.
We are going to use the Hasura GraphQL engine for this as it provides out of the box GraphQL APIs over postgres.
We will use the Hasura GraphQL engine for instantly getting GraphQL APIs over Postgres. Click on the button below to deploy the GraphQL engine to Heroku’s free tier.
This will deploy the
graphql-engine to Heroku. You might need to create a Heroku account if you don’t have one. The
graphql-engine will be running at
your-app with your heroku app name).
Every Hasura cluster comes with an
API Console that you can use to build the backend for your application.
The API Console is available at
To store and compute on geo-location data, we are going to use
PostGIS which is a spatial database extender for
Postgres. It adds support for geographical objects on Postgres and also comes with utility functions such as distance, area, union, and intersection.
Before we begin, we need to enable the PostGIS extension on Postgres. (You’ll need a Postgres instance with PostGIS installed. Heroku Postgres comes with the installation, you just need to create the extension. If you’re using Docker based setup, checkout this docker-compose file)
Data tab in the
Api Console and click on
SQL in nav bar on the left. And execute the following SQL commands:
Please ensure that you select the
Track this checkbox before running the query so that this change is tracked as a migration.
Say we need 2 tables, for user and landmark location data, with the following definitions:
Run the above SQL in the same
SQL section of the console as shown above, and don't forget to check the
Track this checkbox (this is because we want GraphQL Engine to track this change in the db schema).
We are storing the location of the landmark and the user in a column named location of type
GEOGRAPHY(Point) for each table.
Inserting Data using GraphQL
You can populate the tables we just created with test data using the following mutations and variables:
Fetching list of landmarks around a user
In this example, we want to fetch a list of landmarks that are near a given user, along with the user’s details in the same query. PostGIS’ built-in function,
ST_Distance can be used to implement this use case.
Since our use-case requires an output that isn’t a “subset” of any of the existing tables i.e. the
SETOF table doesn’t exist, let’s first create this table and then create our location search function using the following definitions (once again, we’ll use the
SQL section of the Hasura console):
This function fetches user information (for the given input
userid) and a list of landmarks which are less than
distance_kms kilometers away from the user’s location as a JSON field. We can now refer to this function in our GraphQL API and get the corresponding response as shown below:
PostGIS also comes with a variety of other utility functions which you can use. You can find that list here.