Using the GeoJSON format for Geolocation
This guide will help you build a working site on which one can find records in a maximum distance of X km's from given geo point coordinates.
GeoJSON is a geospatial data interchange format based on JSON for encoding a variety of geographic data structures. It defines several types of JSON objects and the manner in which they are combined to represent data about geographic features, their properties, and their spatial extents.
The following geometry types are supported:
-
Point [long, lan]
{ "type": "Point", "coordinates": [100.0, 0.0] }
-
LineString [[long, lan], [long, lan]]
{ "type": "LineString", "coordinates": [ [100.0, 0.0], [10.0, 10.0] ] }
-
Polygon [[[long, lan], [long, lan]]]
{ "type": "Polygon", "coordinates": [ [[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]] ] }
-
MultiPoint [[long, lan], [long, lan]]
{ "type": "MultiPoint", "coordinates": [ [100.0, 0.0], [10.0, 10.0] ] }
To learn more, read the official GeoJSON documentation.
Requirements
To follow the steps in this tutorial, you should be familiar with Tables, data imports, and Form.
Steps
Using the GeoJSON format to find all records in a maximum distance from geopoint coordinates is a four-step process:
Step 1: Prepare Table definition
Create schema/company.yml
:
name: company
properties:
- name: name
type: string
- name: timezone
type: string
- name: city
type: string
- name: location
type: geojson
Step 2: Import data using GraphQL mutation
Create a GraphQL mutation createCompany.graphql
:
mutation createCompany($location: JSONPayload, $city: String, $timezone: String, $name: String){
record_create(
record: {
table: "company"
properties: [
{ name: "name" value: $name }
{ name: "city" value: $city }
{ name: "timezone" value: $timezone }
{ name: "location" value_json: $location }
]
}
) {
id
}
}
Create a payload
:
{
"name": "Company Name",
"city": "Boston",
"timezone": "Timezone",
"location": {
"type": "Point",
"coordinates": [-111.89903, 33.50921]
}
}
Alternatively, you can create the record using a Form:
---
name: create_company
fields:
properties:
name:
validation: { presence: true }
city:
validation: { presence: true }
timezone:
validation: { presence: true }
location:
validation: { geometry: true }
The HTML field snippet for geometry JSON is just a textarea:
<div class="form-group">
<label for="location">Location</label>
<textarea required="true" id="location" type="text" class="form-control" name="">
</textarea>
</div>
Note
This example is for presentation only. In a real scenario, no one would provide a raw JSON as a location address — there would be a JavaScript function using external geolocation services for getting coordinates and then building the required GeometryJSON structure.
Step 3: Prepare GraphQL query
Create the GraphQL query graphql/search.graphql
:
query search($point: GeometryJSON, $distance: Int) {
companies: records(
per_page: 20
name: { value: "modules/geo_records/company" }
filter: {
properties: [
{
name: "location",
distance_sphere: {
center: $point,
distance_in_km: $distance
}
}
]
}) {
results {
properties
}
}
}
Step 4: Create page
To wrap it up, create a page.
app/views/pages/search.liquid
{% parse_json location %}
{
"type": "Point",
"coordinates": [
-111.89903,
33.50921
]
}
{% endparse_json %}
{% assign distance = context.params.distance | default: 100 | plus: 0 %}
{% graphql g = 'search', point: location, distance: distance %}
{% for company in g.companies.results %}
[...]
{% endfor %}
Note
Since the distance
argument has to be an Integer and context.params.distance
is a String, we have to cast this value to Integer.
You can do this by appending a plus filter with a 0
argument - literally adding a 0 converts a string into a number.
Live example and source code
Examples
- Form: https://examples.platform-os.com/geo/companies/new
- Working advanced example: https://examples.platform-os.com/geo/search
Code samples