by Gerard Sans | @gerardsans
Building a
serverless geolocation API
Building a
serverless geolocation API
SANS
GERARD
Developer Advocate AWS
Developer Advocate AWS
International Speaker
Spoken at 143 events in 37 countries
Bike Sharing
Benefits
- Transport flexibility
- Reduce traffic emissions
- Reduce traffic congestion
- Health benefits for users
Santander Cycles
Overview
- Since 2010
- +12,000 Bikes
- 778 stations
Boris Bikes
LNDBikes
Fullstack Serverless
🦄
🌩️
No servers to manage
Fault tolerance High availability
Never pay for idle usage
Auto-scales immediately
Serverless
$
AWS AMPLIFY
Categories
interactions
storage
notifications
auth
analytics
function
amplify add <category>
api
hosting
xr
transcribe
rekognition
translate
comprehend
amplify add predictions
polly
London
Unified API
/BikePoint
/BikePoint/id
TfL Unified API
/BikePoint/Search
[
{
"id": "BikePoints_1",
"commonName": "River Street , Clerkenwell",
"additionalProperties": [{
"key": "NbBikes", "value": "11",
}],
"lat": 51.529163,
"lon": -0.10997
}
// 777 more
]
/BikePoint
{
"id": "BikePoints_1",
"commonName": "River Street , Clerkenwell",
"additionalProperties": [{
"key": "NbBikes", "value": "11",
}],
"lat": 51.529163,
"lon": -0.10997
}
/BikePoint/BikePoints_1
Loading bike stations
Data Transformations
GeoJSONfeature
BikesPoint
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-0.10997, 51.529163]
},
"properties": {
"id": "BikePoints_1",
"name": "River Street , Clerkenwell"
}
}
geoJSON feature
Coordinates = [-0.10997, 51.529163]
51.529163
-0.10997
Coordinates
Data Transformations
GeoJSONfeature
BikesPoint
mapbox Source
mapbox Layer
REST API integration
type BikePoint @model {
id: ID!
name: String!
description: String
location: Location
bikes: Int
}
GraphQL Schema
// request VTL template
{
"version": "2018-05-29",
"method": "GET",
"resourcePath": "/BikePoint/$context.source.id",
}
BikePoint.bikes HTTP Resolver
// response VTL template
#set($body = $util.parseJson($ctx.result.body))
#if($ctx.error)
$util.error($ctx.error.message, $ctx.error.type)
#end
#if($ctx.result.statusCode == 200)
$body.additionalProperties[6].value
#else
#return
#end
BikePoint.bikes HTTP Resolver
Adding Search
type BikePoint @model @searchable {
id: ID!
name: String!
description: String
location: Location
bikes: Int
}
type Location {
lat: Float
lon: Float
}
type Query {
nearbyBikeStations(location: LocationInput!, m: Int, limit: Int)
}
GraphQL Schema
Data Transformations
GeoJSONfeature
BikesPoint
GraphQL API
Elastic Search
# Create index
PUT /bikepoint
# Setup location type as geo_point
PUT /bikepoint/_mapping/doc
{
"properties": {
"location": {
"type": "geo_point"
}
}
}
Elastic Search index
mutation addBikePoint {
createBikePoint(input: {
id: "BikePoints_1"
name: "River Street , Clerkenwell"
location: {
lat: 51.529163
lon: -0.10997
}
}) { id }
}
Automatic indexing
GET /bikepoint/doc/_search
{
"query": {
"bool" : {
"must" : { "match_all" : {} },
"filter" : {
"geo_distance" : {
"distance" : "500m",
"distance_type": "arc",
"location" : {
"lon": -0.134167, "lat": 51.510239
}
Query nearbyBikeStations (1/2)
"sort": [{
"_geo_distance": {
"location": {
"lon": -0.134167, "lat": 51.510239
},
"order": "asc",
"unit": "m",
"distance_type": "arc"
}
}]
}
Query nearbyBikeStations (2/2)
Distance Calculations
[lon1, lat1]
[lon2, lat2]
Haversine Formula
Great-circle distance
Distance Calculations
double distance(double lat1, double lon1, double lat2, double lon2) {
return 6378137 * haversine(lat1, lon1, lat2, lon2);
}
double haversine(double lat1, double lon1, double lat2, double lon2) {
double hsinX = Math.sin((lon1 - lon2) * 0.5);
double hsinY = Math.sin((lat1 - lat2) * 0.5);
double h = hsinY * hsinY + (Math.cos(lat1) * Math.cos(lat2) * hsinX * hsinX);
return 2 * Math.atan2(Math.sqrt(h), Math.sqrt(1 - h));
}
ElasticSearch arc distance (WGS 84)
More
@undef_obj
@kurtiskemple
@dabit3
Kurt Kemple
Richardo
Nader Dabit
@TheSwaminator
Nikhil Swaminathan
Building a Serverless Geolocation Search API Using GraphQL
By Gerard Sans
Building a Serverless Geolocation Search API Using GraphQL
In this talk, we will be using AWS AppSync & Elasticsearch to create a geolocation search service API that will allow users to search within a distance from a given location and display results in a map. We will start designing our schema to introduce the geolocation data, implementing resolvers while discussing best practices and architecture decisions for the presented solution.
- 2,821