This is an introduction to ArangoDB's geo indexes.
ArangoDB uses Hilbert curves to implement geo-spatial indexes. See this blog for details.
A geo-spatial index assumes that the latitude is between -90 and 90 degree and the longitude is between -180 and 180 degree. A geo index will ignore all documents which do not fulfill these requirements.
A geo-spatial constraint makes the same assumptions, but documents not fulfilling these requirements are rejected.
collection.ensureGeoIndex(location)
In case that the index was successfully created, the index identifier is returned.
collection.ensureGeoIndex(location, true
)
http://geojson.org/geojson-spec.html#positions
collection.ensureGeoIndex(latitude, longitude)
In case that the index was successfully created, the index identifier is returned.
Examples
Create an geo index for a list attribute:
arango> db.geo.ensureGeoIndex("loc"); { "id" : "127629/47772301", "type" : "geo1", "geoJson" : false, "fields" : ["loc"], "isNewlyCreated" : true } arango> for (i = -90; i <= 90; i += 10) { .......> for (j = -180; j <= 180; j += 10) { .......> db.geo.save({ name : "Name/" + i + "/" + j, .......> loc: [ i, j ] }); .......> } .......> } arango> db.geo.count(); 703 arango> db.geo.near(0,0).limit(3).toArray(); [ { "_id" : "154092:24861164", "_rev" : 24861164, "name" : "Name/0/0", "loc" : [0, 0]}, { "_id" : "154092:24926700", "_rev" : 24926700, "name" : "Name/0/10", "loc" : [0, 10]}, { "_id" : "154092:22436332", "_rev" : 22436332, "name" : "Name/-10/0", "loc" : [-10, 0]}] arango> db.geo.near(0,0).count(); 100
Create an geo index for a hash array attribute:
arango> db.geo2.ensureGeoIndex("location.latitude", "location.longitude"); { "id" : "87612/1070652", "type" : "geo2", "fields" : ["location.latitude", "location.longitude"], "isNewlyCreated" : true } arango> for (i = -90; i <= 90; i += 10) { .......> for (j = -180; j <= 180; j += 10) { .......> db.geo2.save({ name : "Name/" + i + "/" + j, .......> location: { latitude : i, .......> longitude : j } }); .......> } .......> } arango> db.geo2.near(0,0).limit(3).toArray(); [{ "_id" : "48126444:72964588", "_rev" : 72964588, "location" : { "latitude" : 0, "longitude" : 0}, "name" : "Name/0/0" }, { "_id" : "48126444:73030124", "_rev" : 73030124, "location" : { "latitude" : 0, "longitude" : 10}, "name" : "Name/0/10" }, { "_id" : "48126444:70539756", "_rev" : 70539756, "location" : { "latitude" : -10, "longitude" : 0}, "name" : "Name/-10/0" }]
collection.ensureGeoConstraint(location, ignore-null)
collection.ensureGeoConstraint(location, true
, ignore-null)
collection.ensureGeoConstraint(latitude, longitude, ignore-null)
ensureGeoIndex
but requires that the documents contain a valid geo definition. If ignore-null is true, then documents with a null in location or at least one null in latitude or longitude are ignored.
collection.geo(location)
The next near
or within
operator will use the specific geo-spatial index.
collection.geo(location, true
)
The next near
or within
operator will use the specific geo-spatial index.
collection.geo(latitude, longitude)
The next near
or within
operator will use the specific geo-spatial index.
Examples
Assume you have a location stored as list in the attribute home
and a destination stored in the attribute work
. Than you can use the geo
operator to select, which coordinates to use in a near query.
arango> for (i = -90; i <= 90; i += 10) { .......> for (j = -180; j <= 180; j += 10) { .......> db.complex.save({ name : "Name/" + i + "/" + j, .......> home : [ i, j ], .......> work : [ -i, -j ] }); .......> } .......> } arango> db.complex.near(0, 170).limit(5); exception in file '/simple-query' at 1018,5: an geo-index must be known arango> db.complex.ensureGeoIndex("home"); arango> db.complex.near(0, 170).limit(5).toArray(); [ { _id : 48834092:74655276, _rev : 74655276, name : Name/0/170, home : [ 0, 170 ], work : [ 0, -170 ] }, { _id : 48834092:74720812, _rev : 74720812, name : Name/0/180, home : [ 0, 180 ], work : [ 0, -180 ] }, { _id : 48834092:77080108, _rev : 77080108, name : Name/10/170, home : [ 10, 170 ], work : [ -10, -170 ] }, { _id : 48834092:72230444, _rev : 72230444, name : Name/-10/170, home : [ -10, 170 ], work : [ 10, -170 ] }, { _id : 48834092:72361516, _rev : 72361516, name : Name/0/-180, home : [ 0, -180 ], work : [ 0, 180 ] } ] arango> db.complex.geo("work").near(0, 170).limit(5); exception in file '/simple-query' at 1018,5: an geo-index must be known arango> db.complex.ensureGeoIndex("work"); arango> db.complex.geo("work").near(0, 170).limit(5).toArray(); [ { _id : 48834092:72427052, _rev : 72427052, name : Name/0/-170, home : [ 0, -170 ], work : [ 0, 170 ] }, { _id : 48834092:72361516, _rev : 72361516, name : Name/0/-180, home : [ 0, -180 ], work : [ 0, 180 ] }, { _id : 48834092:70002220, _rev : 70002220, name : Name/-10/-170, home : [ -10, -170 ], work : [ 10, 170 ] }, { _id : 48834092:74851884, _rev : 74851884, name : Name/10/-170, home : [ 10, -170 ], work : [ -10, 170 ] }, { _id : 48834092:74720812, _rev : 74720812, name : Name/0/180, home : [ 0, 180 ], work : [ 0, -180 ] } ]
collection.near(latitude, longitude)
The default will find at most 100 documents near the coordinate (latitude, longitude). The returned list is sorted according to the distance, with the nearest document coming first. If there are near documents of equal distance, documents are chosen randomly from this set until the limit is reached. It is possible to change the limit using the limit operator.
In order to use the near
operator, a geo index must be defined for the collection. This index also defines which attribute holds the coordinates for the document. If you have more then one geo-spatial index, you can use the geo
operator to select a particular index.
near
does not support negative skips. However, you can still use limit
followed to skip
.collection.near(latitude, longitude).limit(limit)
Limits the result to limit documents instead of the default 100.
within
.collection.near(latitude, longitude).distance()
This will add an attribute distance
to all documents returned, which contains the distance between the given point and the document in meter.
collection.near(latitude, longitude).distance(name)
This will add an attribute name to all documents returned, which contains the distance between the given point and the document in meter.
Examples
To get the nearst two locations:
arango> db.geo.near(0,0).limit(2).toArray(); [ { _id : 131840:24773376, _rev : 24773376, name : Name/0/0, loc : [ 0, 0 ] }, { _id : 131840:22348544, _rev : 22348544, name : Name/-10/0, loc : [ -10, 0 ] } ]
If you need the distance as well, then you can use the distance
operator:
arango> db.geo.near(0,0).distance().limit(2).toArray(); [ { _id : 131840:24773376, _rev : 24773376, distance : 0, name : Name/0/0, loc : [ 0, 0 ] }, { _id : 131840:22348544, _rev : 22348544, distance : 1111949.3, name : Name/-10/0, loc : [ -10, 0 ] } ]
collection.within(latitude, longitude, radius)
This will find all documents with in a given radius around the coordinate (latitude, longitude). The returned list is sorted by distance.
In order to use the within
operator, a geo index must be defined for the collection. This index also defines which attribute holds the coordinates for the document. If you have more then one geo-spatial index, you can use the geo
operator to select a particular index.
collection.within(latitude, longitude, radius) .distance()
This will add an attribute _distance
to all documents returned, which contains the distance between the given point and the document in meter.
collection.within(latitude, longitude, radius) .distance(name)
This will add an attribute name to all documents returned, which contains the distance between the given point and the document in meter.
Examples
To find all documents within a radius of 2000 km use:
arango> db.geo.within(0, 0, 2000 * 1000).distance().toArray(); [ { _id : 131840:24773376, _rev : 24773376, distance : 0, name : Name/0/0, loc : [ 0, 0 ] }, { _id : 131840:24707840, _rev : 24707840, distance : 1111949.3, name : Name/0/-10, loc : [ 0, -10 ] }, { _id : 131840:24838912, _rev : 24838912, distance : 1111949.3, name : Name/0/10, loc : [ 0, 10 ] }, { _id : 131840:22348544, _rev : 22348544, distance : 1111949.3, name : Name/-10/0, loc : [ -10, 0 ] }, { _id : 131840:27198208, _rev : 27198208, distance : 1111949.3, name : Name/10/0, loc : [ 10, 0 ] }, { _id : 131840:22414080, _rev : 22414080, distance : 1568520.6, name : Name/-10/10, loc : [ -10, 10 ] }, { _id : 131840:27263744, _rev : 27263744, distance : 1568520.6, name : Name/10/10, loc : [ 10, 10 ] }, { _id : 131840:22283008, _rev : 22283008, distance : 1568520.6, name : Name/-10/-10, loc : [ -10, -10 ] }, { _id : 131840:27132672, _rev : 27132672, distance : 1568520.6, name : Name/10/-10, loc : [ 10, -10 ] } ]