Finding the nearest locations around you using AWS Amplify — Part 1

Before you continue

In case you are not familiar with AWS Amplify or AWS AppSync, I recommend you the following articles:

Step 1: change your GraphQL Schema to include location coordinates

The first thing you need to do, is to add geolocation fields and types to your GraphQL Schema. This will allow you to store geolocation data, run distance-aware searches and display the results in a map like the one below.

LondonCycles app showing live status for nearby Santander Cycles bike stations.

Introduction to geolocation

Geolocation is an estimation of a geographic location with the purpose to position an object in a map, usually in the shape of a marker. One way to do this is by providing its longitude and latitude.

(-0.109971, 51.529163)   // GPS/WGS84 (long, lat) 
[-0.109971, 51.529163] // GeoJSON [long, lat]
51°31'44''N, 0°6'35''W // DMS Degrees Minutes Seconds
gcpvjkxgjkpwmsp // Geohash
(-0.1099 , 51.5291) // Use 4 digits for 10m precision
(-0.10997 , 51.52916) // Use 5 digits for 1m precision
(-0.109971, 51.529163) // Use 6 digits for .1m precision

Adding geolocation to your GraphQL Schema

We have seen, that in order to position an object in a map, we need to provide its location coordinates. Add a location field to an existing type using @model in your schema. For our example, using bike stations, we did the following changes to the BikePoint type:

type BikePoint @model {   
location: Location!
}
type Location {
lat: Float!
lon: Float!
}

Learn the basics of GraphQL including Schema definition at graphql.org.

Step 2: enable distance-aware searches using @searchable

In this step, we are going to take advantage of @searchable GraphQL transform provided by AWS AppSync to enable advanced searches including distance-aware searches.

GraphQL mutations mapping while using @searchable GraphQL transform
////////////////////////////////////////////////////////////////////
// Step 1: run GraphQL mutation (simplified)
$input = {
"id": "BikePoints_1",
"name": "River Street , Clerkenwell",
"location": {
"lat": 51.529163,
"lon": -0.109971
},
}
mutation createBikePoint($input: CreateBikePointInput!) {
createBikePoint(input:$input) {
id name location { lat lon }
}
}
////////////////////////////////////////////////////////////////////
// Step 2: run AWS AppSync Resolver DynamoDB mapping (simplified)
{
"version": "2017-02-28",
"operation": "PutItem",
"id": "BikePoints_1",
"attributeValues": {
"__typename": "BikePoint",
"name": "River Street , Clerkenwell",
"location": {
"lat": 51.529163,
"lon": -0.109971
},
}
}
////////////////////////////////////////////////////////////////////// Step 3: process DynamoDB Stream Event Record (simplified){
"eventID": "...",
"eventName": "INSERT",
"eventSource": "aws:dynamodb",
"awsRegion": "us-west-1",
"dynamodb": {
"Keys": {
"id": { "S": "BikePoints_1" },
},
"NewImage": {
"name": { "S": "River Street , Clerkenwell" },
...
},
},
"eventSourceARN": "arn:aws:...table/BikePoint/stream/..."
}
////////////////////////////////////////////////////////////////////
// Step 4: run Elasticsearch document operation (simplified)
PUT /bikepoint/_mapping/doc
{
"properties": {
"id": "BikePoints_1"
"name": "River Street , Clerkenwell",
"location": {
"lat": 51.529163,
"lon": -0.109971
}
}
}

Adding searchable GraphQL transform

Add the searchable transform to the type you want to enable geolocation searches as shown below

type BikePoint @model @searchable {   
location: Location
}
type Location {
lat: Float!
lon: Float!
}

Pushing changes to the cloud

Run the following command to enable searches for your GraphQL type:

amplify push

Default search query: SearchBikePoints

AWS AppSync creates a default search query for you so you can try out some searches for your type. These searches automatically support the following GraphQL types: ID, String, Int, Float and Boolean.

query SearchBikePoints(...) 
{
searchBikePoints(...) {
items {
id name location { lat lon }
}
nextToken
total
}
}

Conclusion

Well done! You have learnt how to enable GraphQL distance-aware searches using @searchable and a bit more of how it works behind the scenes. Try it out!

Ready to code?

You don’t have an AWS Account? Use the next few minutes to create one and activate the free plan for a whole year. Follow steps at AWS knowledge center.

Free tier for a new AWS Account. Check out latest pricing.

Thanks for reading!

Have you got any questions regarding this article AWS Amplify or AWS AppSync? Feel free to ping me anytime at @gerardsans.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Gerard Sans

Gerard Sans

Helping Devs to succeed #AI #web3 / ex @AWSCloud / Just be AWSome / MC Speaker Trainer Community Leader @web3_london / @ReactEurope @ReactiveConf @ngcruise