ArangoDB v3.13 is under development and not released yet. This documentation is not final and potentially incomplete.
Geospatial queries
Geospatial coordinates consisting of a latitude and longitude value can be stored either as two separate attributes, or as a single attribute in the form of an array with both numeric values. ArangoDB can index such coordinates for fast geospatial queries.
Locations data
Insert some filming locations into a new collection called Locations
,
which you need to create first, and then run below AQL query:
LET places = [
{ "name": "Dragonstone", "coordinates": [ 55.167801, -6.815096 ] },
{ "name": "King's Landing", "coordinates": [ 42.639752, 18.110189 ] },
{ "name": "The Red Keep", "coordinates": [ 35.896447, 14.446442 ] },
{ "name": "Yunkai", "coordinates": [ 31.046642, -7.129532 ] },
{ "name": "Astapor", "coordinates": [ 31.50974, -9.774249 ] },
{ "name": "Winterfell", "coordinates": [ 54.368321, -5.581312 ] },
{ "name": "Vaes Dothrak", "coordinates": [ 54.16776, -6.096125 ] },
{ "name": "Beyond the wall", "coordinates": [ 64.265473, -21.094093 ] }
]
FOR place IN places
INSERT place INTO Locations
RETURN GEO_POINT(NEW.coordinates[1], NEW.coordinates[0])
The last line of the query returns the locations as GeoJSON Points to make the web interface render a map with markers to give you a visualization of where the filming locations are. Note that the coordinate order is longitude, than latitude with GeoJSON, whereas the dataset uses latitude, longitude.
Geospatial index
To query based on coordinates, a geo index is required. It determines which fields contain the latitude and longitude values.
- Click Collections in the main navigation.
- Click the name or row of the Locations collection.
- Switch to the Indexes tab at the top.
- Click the Add Index button.
- Change the Type to Geo Index.
- Enter
coordinates
into Fields. - Click the Create button to confirm.
Find nearby locations
A FOR
loop is used again, with a subsequent SORT
operation based on the
DISTANCE()
between a stored coordinate pair and a coordinate pair given in a query.
This pattern is recognized by the query optimizer. A geo index will be used to
accelerate such queries if one is available.
The default sorting direction is ascending, so a query finds the coordinates
closest to the reference point first (lowest distance). LIMIT
can be used
to restrict the number of results to at most n matches.
In below example, the limit is set to 3. The origin (the reference point) is a coordinate pair somewhere downtown in Dublin, Ireland:
FOR loc IN Locations
LET distance = DISTANCE(loc.coordinates[0], loc.coordinates[1], 53.35, -6.25)
SORT distance
LIMIT 3
RETURN {
name: loc.name,
latitude: loc.coordinates[0],
longitude: loc.coordinates[1],
distance
}
[
{
"name": "Vaes Dothrak",
"latitude": 54.16776,
"longitude": -6.096125,
"distance": 91491.58596795711
},
{
"name": "Winterfell",
"latitude": 54.368321,
"longitude": -5.581312,
"distance": 121425.66829502625
},
{
"name": "Dragonstone",
"latitude": 55.167801,
"longitude": -6.815096,
"distance": 205433.7784182078
}
]
The query returns the location name, as well as the coordinates and the
calculated distance in meters. The coordinates are returned as two separate
attributes. You may return just the document with a simple RETURN loc
instead
if you want. Or return the whole document with an added distance attribute using
RETURN MERGE(loc, { distance })
.
Find locations within radius
LIMIT
can be swapped out with a FILTER
that checks the distance, to find
locations within a given radius from a reference point. Remember that the unit
is meters. The example uses a radius of 200,000 meters (200 kilometers):
FOR loc IN Locations
LET distance = DISTANCE(loc.coordinates[0], loc.coordinates[1], 53.35, -6.25)
SORT distance
FILTER distance < 200 * 1000
RETURN {
name: loc.name,
latitude: loc.coordinates[0],
longitude: loc.coordinates[1],
distance: ROUND(distance / 1000)
}
[
{
"name": "Vaes Dothrak",
"latitude": 54.16776,
"longitude": -6.096125,
"distance": 91
},
{
"name": "Winterfell",
"latitude": 54.368321,
"longitude": -5.581312,
"distance": 121
}
]
The distances are converted to kilometers and rounded for readability.