Geospatial data can be defined as any dataset which has a location tag attached to it, i.e.: a pair of coordinates which allows us to position it precisely at the surface of the earth. In this post we are going to describe how we can make geospatial data available on the web, trough a RESTfull API, so that ourselves or others can do something with it, for instance creating a map. If it is true you can create a map using a static file, using an API has numerous advantages like scalability, reliability and updatability. In order to do this, we will use three things: a dataset, a standard and a stack of Free and Open Source Software (FOSS).
Dataset
In this tutorial we will share a dataset with local shops and products in the city of Barcelona, kindly provided by sawcer.
Each record describes characteristics of the shop such as name
, address
, website
, which products
are sold (e.g.: Gluten free donut) and, last but not the least, its location as a point geometry, with x,y
coordinates.
Standard
Standards are the glue in the server-client architecture. The Open Geospatial Consortium(OGC) is a member organisation, which publishes standards to ensure the maximum degree of interoperability between geospatial data and services. In practice interoperability would mean that you could write a client application that talks to any server, without knowing any details about that server's implementation.
In this tutorial we will use the OGC API Features standard, which was designed for sharing feature data over the web (if you are wondering what a feature is, you can check out this article). These are some of its main traits, which make it very convenient to use:
Software Stack
In order to publish the dataset using the OGC API Features standard, we need a software which implements the standard. In this tutorial we will use pygeoapi, which is a python server implementation, released under a FOSS (MIT) license. pygeoapi needs a backend to store the data. For that we will use the MongoDB document oriented database. In order to make deployment easier, the complete stack was virtualised into a set of docker containers, and orchestrated using docker-compose.
Putting it all together
In order to publish the dataset, you can clone this repository. If you navigate to the docker/examples/mongo folder, you will find this docker-composition:
version: '3.3'
services:
pygeoapi:
image: geopython/pygeoapi:latest
container_name: pygeoapi_mongo
entrypoint:
- /mongo-entrypoint.sh
ports:
- 5000:80
volumes:
- ./pygeoapi/docker.config.yml:/pygeoapi/local.config.yml
- ./pygeoapi/mongo-entrypoint.sh:/mongo-entrypoint.sh
- ./pygeoapi/wait-for-mongo.sh:/wait-for-mongo.sh
links:
- mongo
depends_on:
- mongo
mongo:
image: mongo
container_name: mongo
ports:
- 27017:27017
volumes:
- ./docker-entrypoint-initdb.d/add_data.sh:/docker-entrypoint-initdb.d/add_data.sh:ro
- ./mongo_data/:/mongo_data
environment:
MONGO_INITDB_DATABASE: sawcer
mongo-express:
image: mongo-express
restart: always
container_name: mongo_express
links:
- mongo
depends_on:
- mongo
ports:
- 8081:8081
mongodb://root:example@mongo:27017/
volumes:
mongo_data: {}
Here is what happens behind the scenes, when you type docker-compose up
:
- The
mongo
container starts, a database is initialised and the data is injected into a collection. The data is pulled from a GeoJSON file in themongo_data
folder. If you are trying this with your own data, it is worth to mention that mongo ingests the features array, without the outer element. You can transform a regular GeoJSON file into MongoDB-consumable JSON, using the jq command-line utility:jq --compact-output ".features" shops-orig.geojson > shops.geojson
- Once the database is live, the
pygeoapi
container starts. The configuration of the service is on this file, which is mounted by the container. In particular, this bit is where the sawcer dataset is exposed from the MongoDB backend:
sawcer:
type: collection
title: Shops and Products
description: SEARCH & FIND & SHARE where to get ingredients in local shops
keywords:
- cases
links:
- type: text/html
rel: canonical
title: information
href: https://www.sawcer.com/
hreflang: en-US
extents:
spatial:
bbox: [-180, -90, 180, 90]
crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84
temporal:
begin: 2011-11-11
end: null # or empty
providers:
- type: feature
name: MongoDB
data: mongodb://mongo:27017/sawcer
collection: shops
At this stage, the pygeoapi is running on port 5000
: http://localhost:5000
. You can access the sawcer dataset at: http://localhost:5000/collections/sawcer
You can retrieve the collection items at:
http://localhost:5000/collections/sawcer/items
The default response is in html, but you can change it using the f
(format) parameter. The server supports both, JSON and JSON-LD encodings. For instance:
http://localhost:5000/collections/sawcer/items?f=jsonld
You can access one particular item, using its id:
http://localhost:5000/collections/sawcer/items/61afae9fc6bf8d516533620f
If you want to explore the MongoDB collection, you can use the provided mongo-express user interface, running on port 8081
: http://localhost:8081
What's next
Making your geospatial dataset available on the web using a standard, unlocks a world of possibilities. It means that many existing (or future) client applications will be able to read your data, out-of-the-box. For instance, anyone can use QGIS, Esri ArcGIS, React-leaflet, OpenLayers or Python OWSlib to pull your data and analyse it, or create products or services on top of it.
You can explore a live deployment of this dataset, at this endpoint:
https://features.byteroad.net/collections/sawcer
On this OpenAPI document, you can try all the available endpoints:
https://features.byteroad.net/openapi?f=html
Top comments (0)