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
#endBikePoint.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.
- 4,293
 
     
   
   
  