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.

Getting started

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.

Click this button to deploy the GraphQL to Heroku

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 https://your-app.herokuapp.com (replace your-app with your heroku app name).

API Console

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 https://your-app.herokuapp.com/console

PostGIS

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.

Enabling PostGIS

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)

Head to 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.

Creating tables

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 Data -> 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:

query:

example response:

Conclusion

PostGIS also comes with a variety of other utility functions which you can use. You can find that list here.


Hasura is an open-source engine that gives you realtime GraphQL APIs on new or existing Postgres databases, with built-in support for stitching custom GraphQL APIs and triggering web hooks on database changes.


Hasura

Hasura

The Hasura GraphQL Engine gives you realtime, high performance GraphQL on any Postgres app. Now supports event triggers for use with serverless.

Read More