Geo Indexes

    AQL’s geographic features are described in Geo functions.

    ArangoDB uses Hilbert curves to implement geo-spatial indexes.See this for details.

    A geo-spatial index assumes that the latitude is between -90 and 90 degree andthe longitude is between -180 and 180 degree. A geo index will ignore alldocuments which do not fulfill these requirements.

    Accessing Geo Indexes from the Shell

    ensures that a geo index exists

    Creates a geo-spatial index on all documents using location as path tothe coordinates. The value of the attribute has to be an array with at least twonumeric values. The array must contain the latitude (first value) and thelongitude (second value).

    All documents, which do not have the attribute path or have a non-conformingvalue in it are excluded from the index.

    A geo index is implicitly sparse, and there is no way to control its sparsity.

    In case that the index was successfully created, an object with the indexdetails, including the index-identifier, is returned.

    To create a geo index on an array attribute that contains longitude first, set thegeoJson attribute to true. This corresponds to the format described in

    collection.ensureIndex({ type: "geo", fields: [ "location" ], geoJson: true })

    To create a geo-spatial index on all documents using latitude andlongitude as separate attribute paths, two paths need to be specifiedin the fields array:

    collection.ensureIndex({ type: "geo", fields: [ "latitude", "longitude" ] })

    In case that the index was successfully created, an object with the indexdetails, including the index-identifier, is returned.

    Examples

    Create a geo index for an array attribute:

    Show execution results

    1. {
    2. "constraint" : false,
    3. "fields" : [
    4. "loc"
    5. ],
    6. "geoJson" : false,
    7. "id" : "geo/24791",
    8. "ignoreNull" : true,
    9. "isNewlyCreated" : true,
    10. "sparse" : true,
    11. "type" : "geo1",
    12. "unique" : false,
    13. "code" : 201
    14. }
    15. 703
    16. [
    17. {
    18. "_key" : "25848",
    19. "_id" : "geo/25848",
    20. "_rev" : "_ZHpY3mC--_",
    21. "name" : "Name/0/0",
    22. "loc" : [
    23. 0,
    24. 0
    25. ]
    26. },
    27. {
    28. "_key" : "25851",
    29. "_id" : "geo/25851",
    30. "_rev" : "_ZHpY3mC--B",
    31. "name" : "Name/0/10",
    32. "loc" : [
    33. 0,
    34. 10
    35. ]
    36. },
    37. {
    38. "_key" : "25737",
    39. "_id" : "geo/25737",
    40. "_rev" : "_ZHpY3la--B",
    41. "name" : "Name/-10/0",
    42. "loc" : [
    43. -10,
    44. 0
    45. ]
    46. }
    47. ]
    48. null

    Hide execution results

    Create a geo index for a hash array attribute:

    1. arangosh> db.geo2.ensureIndex({ type: "geo", fields: [ "location.latitude", "location.longitude" ] });
    2. arangosh> for (i = -90; i <= 90; i += 10) {
    3. ........> for (j = -180; j <= 180; j += 10) {
    4. ........> db.geo2.save({ name : "Name/" + i + "/" + j, location: { latitude : i, longitude : j } });
    5. ........> }
    6. ........> }
    7. arangosh> db.geo2.near(0, 0).limit(3).toArray();

    Show execution results

    1. {
    2. "constraint" : false,
    3. "fields" : [
    4. "location.latitude",
    5. "location.longitude"
    6. ],
    7. "id" : "geo2/26918",
    8. "ignoreNull" : true,
    9. "isNewlyCreated" : true,
    10. "sparse" : true,
    11. "type" : "geo2",
    12. "unique" : false,
    13. "code" : 201
    14. }
    15. [
    16. {
    17. "_key" : "27975",
    18. "_id" : "geo2/27975",
    19. "_rev" : "_ZHpY30C--F",
    20. "name" : "Name/0/0",
    21. "location" : {
    22. "latitude" : 0,
    23. "longitude" : 0
    24. }
    25. },
    26. {
    27. "_key" : "27978",
    28. "_id" : "geo2/27978",
    29. "_rev" : "_ZHpY30G--_",
    30. "name" : "Name/0/10",
    31. "location" : {
    32. "latitude" : 0,
    33. "longitude" : 10
    34. }
    35. },
    36. {
    37. "_key" : "27864",
    38. "_id" : "geo2/27864",
    39. "_rev" : "_ZHpY3za--D",
    40. "name" : "Name/-10/0",
    41. "location" : {
    42. "latitude" : -10,
    43. "longitude" : 0
    44. }
    45. }
    46. ]

    Hide execution results

    Use GeoIndex with AQL SORT statement:

    1. arangosh> db.geoSort.ensureIndex({ type: "geo", fields: [ "latitude", "longitude" ] });
    2. arangosh> for (i = -90; i <= 90; i += 10) {
    3. ........> for (j = -180; j <= 180; j += 10) {
    4. ........> db.geoSort.save({ name : "Name/" + i + "/" + j, latitude : i, longitude : j });
    5. ........> }
    6. ........> }
    7. arangosh> var query = "FOR doc in geoSort SORT DISTANCE(doc.latitude, doc.longitude, 0, 0) LIMIT 5 RETURN doc"
    8. arangosh> db._explain(query, {}, {colors: false});
    9. arangosh> db._query(query);

    Show execution results

    1. {
    2. "constraint" : false,
    3. "fields" : [
    4. "latitude",
    5. "longitude"
    6. ],
    7. "id" : "geoSort/33288",
    8. "ignoreNull" : true,
    9. "isNewlyCreated" : true,
    10. "sparse" : true,
    11. "type" : "geo2",
    12. "unique" : false,
    13. "code" : 201
    14. }
    15. Query string:
    16. FOR doc in geoSort SORT DISTANCE(doc.latitude, doc.longitude, 0, 0) LIMIT 5 RETURN doc
    17.  
    18. Execution plan:
    19. Id NodeType Est. Comment
    20. 1 SingletonNode 1 * ROOT
    21. 7 IndexNode 703 - FOR doc IN geoSort /* geo2 index scan */
    22. 5 LimitNode 5 - LIMIT 0, 5
    23. 6 ReturnNode 5 - RETURN doc
    24.  
    25. Indexes used:
    26. By Type Collection Unique Sparse Selectivity Fields Ranges
    27. 7 geo2 geoSort false true n/a [ `latitude`, `longitude` ] NEAR(doc, 0, 0)
    28.  
    29. Optimization rules applied:
    30. Id RuleName
    31. 1 geo-index-optimizer
    32. 2 remove-unnecessary-calculations-2
    33.  
    34.  
    35. [
    36. {
    37. "_key" : "34345",
    38. "_id" : "geoSort/34345",
    39. "_rev" : "_ZHpY4n---H",
    40. "name" : "Name/0/0",
    41. "latitude" : 0,
    42. "longitude" : 0
    43. },
    44. {
    45. "_key" : "34234",
    46. "_id" : "geoSort/34234",
    47. "_rev" : "_ZHpY4mW--G",
    48. "name" : "Name/-10/0",
    49. "latitude" : -10,
    50. "longitude" : 0
    51. },
    52. {
    53. "_key" : "34342",
    54. "_id" : "geoSort/34342",
    55. "_rev" : "_ZHpY4n---F",
    56. "name" : "Name/0/-10",
    57. "latitude" : 0,
    58. "longitude" : -10
    59. },
    60. {
    61. "_key" : "34348",
    62. "_id" : "geoSort/34348",
    63. "_rev" : "_ZHpY4nC--_",
    64. "name" : "Name/0/10",
    65. "latitude" : 0,
    66. "longitude" : 10
    67. },
    68. {
    69. "_key" : "34456",
    70. "_id" : "geoSort/34456",
    71. "_rev" : "_ZHpY4nm--D",
    72. "name" : "Name/10/0",
    73. "latitude" : 10,
    74. "longitude" : 0
    75. }
    76. ]
    77. [object ArangoQueryCursor, count: 5, cached: false, hasMore: false]

    Hide execution results

    Use GeoIndex with AQL FILTER statement:

    Show execution results

    1. {
    2. "constraint" : false,
    3. "fields" : [
    4. "latitude",
    5. "longitude"
    6. ],
    7. "id" : "geoFilter/29039",
    8. "ignoreNull" : true,
    9. "isNewlyCreated" : true,
    10. "sparse" : true,
    11. "type" : "geo2",
    12. "unique" : false,
    13. "code" : 201
    14. }
    15. Query string:
    16. FOR doc in geoFilter FILTER DISTANCE(doc.latitude, doc.longitude, 0, 0) < 2000 RETURN doc
    17.  
    18. Execution plan:
    19. Id NodeType Est. Comment
    20. 1 SingletonNode 1 * ROOT
    21. 6 IndexNode 703 - FOR doc IN geoFilter /* geo2 index scan */
    22. 5 ReturnNode 703 - RETURN doc
    23.  
    24. Indexes used:
    25. By Type Collection Unique Sparse Selectivity Fields Ranges
    26.  
    27. Optimization rules applied:
    28. Id RuleName
    29. 1 geo-index-optimizer
    30. 2 remove-unnecessary-calculations-2
    31.  
    32.  
    33. [
    34. {
    35. "_key" : "30096",
    36. "_id" : "geoFilter/30096",
    37. "_rev" : "_ZHpY4Cq--B",
    38. "name" : "Name/0/0",
    39. "latitude" : 0,
    40. "longitude" : 0
    41. }
    42. ]
    43. [object ArangoQueryCursor, count: 1, cached: false, hasMore: false]

    Hide execution results

    Looks up a geo index defined on attribute location_attribute.

    Returns a geo index object if an index was found. The near orwithin operators can then be used to execute a geo-spatial query onthis particular index.

    This is useful for collections with multiple defined geo indexes.

    collection.geo(location_attribute, true)

    Looks up a geo index on a compound attribute location_attribute.

    Returns a geo index object if an index was found. The near orwithin operators can then be used to execute a geo-spatial query onthis particular index.

    collection.geo(latitude_attribute, longitude_attribute)

    Looks up a geo index defined on the two attributes latitude_attribute_and _longitude-attribute.

    Returns a geo index object if an index was found. The near or operators can then be used to execute a geo-spatial query onthis particular index.

    Note: this method is not yet supported by the RocksDB storage engine.

    Note: the geo simple query helper function is deprecated as of ArangoDB2.6. The function may be removed in future versions of ArangoDB. The preferredway for running geo queries is to use their AQL equivalents.

    Examples

    Assume you have a location stored as list in the attribute home_and a destination stored in the attribute _work. Then you can use thegeo operator to select which geo-spatial attributes (and thus whichindex) to use in a near query.

    1. arangosh> for (i = -90; i <= 90; i += 10) {
    2. ........> for (j = -180; j <= 180; j += 10) {
    3. ........> db.complex.save({ name : "Name/" + i + "/" + j,
    4. ........> home : [ i, j ],
    5. ........> work : [ -i, -j ] });
    6. ........> }
    7. ........> }
    8. ........>
    9. arangosh> db.complex.near(0, 170).limit(5);
    10. [ArangoError 1570: no suitable geo index found for geo restriction on 'complex']
    11. arangosh> db.complex.ensureIndex({ type: "geo", fields: [ "home" ] });
    12. {
    13. "constraint" : false,
    14. "fields" : [
    15. "home"
    16. ],
    17. "geoJson" : false,
    18. "id" : "complex/33269",
    19. "ignoreNull" : true,
    20. "isNewlyCreated" : true,
    21. "sparse" : true,
    22. "type" : "geo1",
    23. "unique" : false,
    24. "code" : 201
    25. }
    26. arangosh> db.complex.near(0, 170).limit(5).toArray();
    27. [
    28. {
    29. "_key" : "32263",
    30. "_id" : "complex/32263",
    31. "_rev" : "_ZHpY4VO--H",
    32. "name" : "Name/0/170",
    33. "home" : [
    34. 0,
    35. 170
    36. ],
    37. "work" : [
    38. 0,
    39. -170
    40. ]
    41. },
    42. {
    43. "_key" : "32266",
    44. "_id" : "complex/32266",
    45. "_rev" : "_ZHpY4VS--_",
    46. "name" : "Name/0/180",
    47. "home" : [
    48. 0,
    49. 180
    50. ],
    51. "work" : [
    52. 0,
    53. -180
    54. ]
    55. },
    56. {
    57. "_key" : "32152",
    58. "_id" : "complex/32152",
    59. "_rev" : "_ZHpY4Uu--_",
    60. "name" : "Name/-10/170",
    61. "home" : [
    62. -10,
    63. 170
    64. ],
    65. "work" : [
    66. 10,
    67. -170
    68. ]
    69. },
    70. {
    71. "_key" : "32374",
    72. "_id" : "complex/32374",
    73. "_rev" : "_ZHpY4V2--_",
    74. "name" : "Name/10/170",
    75. "home" : [
    76. 10,
    77. 170
    78. ],
    79. "work" : [
    80. -10,
    81. -170
    82. ]
    83. },
    84. {
    85. "_key" : "32158",
    86. "_id" : "complex/32158",
    87. "_rev" : "_ZHpY4Uu--D",
    88. "name" : "Name/0/-180",
    89. "home" : [
    90. 0,
    91. -180
    92. ],
    93. "work" : [
    94. 0,
    95. 180
    96. ]
    97. }
    98. ]
    99. arangosh> db.complex.geo("work").near(0, 170).limit(5);
    100. [ArangoError 1570: no suitable geo index found for geo restriction on 'complex']
    101. arangosh> db.complex.ensureIndex({ type: "geo", fields: [ "work" ] });
    102. {
    103. "constraint" : false,
    104. "fields" : [
    105. "work"
    106. ],
    107. "geoJson" : false,
    108. "id" : "complex/33277",
    109. "ignoreNull" : true,
    110. "isNewlyCreated" : true,
    111. "sparse" : true,
    112. "type" : "geo1",
    113. "unique" : false,
    114. "code" : 201
    115. }
    116. arangosh> db.complex.geo("work").near(0, 170).limit(5).toArray();
    117. [
    118. {
    119. "_key" : "32263",
    120. "_id" : "complex/32263",
    121. "_rev" : "_ZHpY4VO--H",
    122. "name" : "Name/0/170",
    123. "home" : [
    124. 0,
    125. 170
    126. ],
    127. "work" : [
    128. 0,
    129. -170
    130. ]
    131. },
    132. {
    133. "_key" : "32266",
    134. "_id" : "complex/32266",
    135. "_rev" : "_ZHpY4VS--_",
    136. "name" : "Name/0/180",
    137. "home" : [
    138. 0,
    139. 180
    140. ],
    141. "work" : [
    142. 0,
    143. -180
    144. ]
    145. },
    146. {
    147. "_key" : "32152",
    148. "_id" : "complex/32152",
    149. "_rev" : "_ZHpY4Uu--_",
    150. "name" : "Name/-10/170",
    151. "home" : [
    152. -10,
    153. 170
    154. ],
    155. "work" : [
    156. 10,
    157. -170
    158. ]
    159. },
    160. {
    161. "_key" : "32374",
    162. "_id" : "complex/32374",
    163. "_rev" : "_ZHpY4V2--_",
    164. "name" : "Name/10/170",
    165. "home" : [
    166. 10,
    167. 170
    168. ],
    169. "work" : [
    170. -10,
    171. -170
    172. ]
    173. },
    174. {
    175. "_key" : "32158",
    176. "_id" : "complex/32158",
    177. "_rev" : "_ZHpY4Uu--D",
    178. "name" : "Name/0/-180",
    179. "home" : [
    180. 0,
    181. -180
    182. ],
    183. "work" : [
    184. 0,
    185. 180
    186. ]
    187. }
    188. ]

    Hide execution results

    1. arangosh> for (i = -90; i <= 90; i += 10) {
    2. ........> for (j = -180; j <= 180; j += 10) {
    3. ........> db.complex.save({ name : "Name/" + i + "/" + j,
    4. ........> home : [ i, j ],
    5. ........> work : [ -i, -j ] });
    6. ........> }
    7. ........> }
    8. ........>
    9. arangosh> db.complex.ensureIndex({ type: "geo", fields: [ "home" ] });
    10. arangosh> db.complex.near(0, 170).limit(5).toArray();
    11. arangosh> db.complex.geo("work").near(0, 170).limit(5);
    12. arangosh> db.complex.ensureIndex({ type: "geo", fields: [ "work" ] });
    13. arangosh> db.complex.geo("work").near(0, 170).limit(5).toArray();

    Show execution results

    constructs a near query for a collectioncollection.near(latitude, longitude)

    The returned list is sorted according to the distance, with the nearestdocument to the coordinate (latitude, longitude) coming first.If there are near documents of equal distance, documents are chosen randomlyfrom this set until the limit is reached. It is possible to change the limitusing the limit operator.

    In order to use the near operator, a geo index must be defined for thecollection. This index also defines which attribute holds the coordinatesfor the document. If you have more then one geo-spatial index, you can usethe geo operator to select a particular index.

    Note: 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.

    Note: Unlike with multiple explicit limits, limit will raisethe implicit default limit imposed by within.

    collection.near(latitude, longitude).distance()

    This will add an attribute distance to all documents returned, whichcontains the distance between the given point and the document in meters.

    collection.near(latitude, longitude).distance(name)

    Note: this method is not yet supported by the RocksDB storage engine.

    Note: the near simple query function is deprecated as of ArangoDB 2.6.The function may be removed in future versions of ArangoDB. The preferredway for retrieving documents from a collection using the near operator isto use the AQL NEAR function in an AQL query as follows:

    1. RETURN doc

    Examples

    To get the nearest two locations:

    1. arangosh> db.geo.ensureIndex({ type: "geo", fields: [ "loc" ] });
    2. {
    3. "constraint" : false,
    4. "fields" : [
    5. "loc"
    6. ],
    7. "geoJson" : false,
    8. "id" : "geo/219",
    9. "ignoreNull" : true,
    10. "isNewlyCreated" : true,
    11. "sparse" : true,
    12. "type" : "geo1",
    13. "unique" : false,
    14. "code" : 201
    15. }
    16. arangosh> for (var i = -90; i <= 90; i += 10) {
    17. ........> for (var j = -180; j <= 180; j += 10) {
    18. ........> db.geo.save({
    19. ........> name : "Name/" + i + "/" + j,
    20. ........> loc: [ i, j ] });
    21. ........> } }
    22. arangosh> db.geo.near(0, 0).limit(2).toArray();
    23. [
    24. {
    25. "_key" : "1276",
    26. "_id" : "geo/1276",
    27. "_rev" : "_ZHpYUQG--D",
    28. "name" : "Name/0/0",
    29. "loc" : [
    30. 0,
    31. 0
    32. ]
    33. },
    34. {
    35. "_key" : "1165",
    36. "_id" : "geo/1165",
    37. "_rev" : "_ZHpYUPe--F",
    38. "name" : "Name/-10/0",
    39. "loc" : [
    40. -10,
    41. 0
    42. ]
    43. }
    44. ]

    Hide execution results

    Show execution results

    If you need the distance as well, then you can use the distanceoperator:

    1. arangosh> db.geo.ensureIndex({ type: "geo", fields: [ "loc" ] });
    2. {
    3. "constraint" : false,
    4. "fields" : [
    5. "loc"
    6. ],
    7. "geoJson" : false,
    8. "id" : "geo/2340",
    9. "ignoreNull" : true,
    10. "isNewlyCreated" : true,
    11. "sparse" : true,
    12. "type" : "geo1",
    13. "unique" : false,
    14. "code" : 201
    15. }
    16. arangosh> for (var i = -90; i <= 90; i += 10) {
    17. ........> for (var j = -180; j <= 180; j += 10) {
    18. ........> db.geo.save({
    19. ........> name : "Name/" + i + "/" + j,
    20. ........> loc: [ i, j ] });
    21. ........> } }
    22. arangosh> db.geo.near(0, 0).distance().limit(2).toArray();
    23. [
    24. {
    25. "distance" : 0,
    26. "_id" : "geo/3397",
    27. "_key" : "3397",
    28. "_rev" : "_ZHpYUei--_",
    29. "loc" : [
    30. 0,
    31. 0
    32. ],
    33. "name" : "Name/0/0"
    34. },
    35. {
    36. "distance" : 1111949.2664455874,
    37. "_id" : "geo/3286",
    38. "_key" : "3286",
    39. "_rev" : "_ZHpYUeC--J",
    40. "loc" : [
    41. -10,
    42. 0
    43. ],
    44. "name" : "Name/-10/0"
    45. }
    46. ]

    Hide execution results

    1. arangosh> db.geo.ensureIndex({ type: "geo", fields: [ "loc" ] });
    2. arangosh> for (var i = -90; i <= 90; i += 10) {
    3. ........> for (var j = -180; j <= 180; j += 10) {
    4. ........> db.geo.save({
    5. ........> name : "Name/" + i + "/" + j,
    6. ........> loc: [ i, j ] });
    7. ........> } }
    8. arangosh> db.geo.near(0, 0).distance().limit(2).toArray();

    Show execution results

    constructs a within query for a collectioncollection.within(latitude, longitude, radius)

    This will find all documents within a given radius around the coordinate(latitude, longitude). The returned array is sorted by distance,beginning with the nearest document.

    In order to use the within operator, a geo index must be defined for thecollection. This index also defines which attribute holds the coordinatesfor the document. If you have more then one geo-spatial index, you can usethe geo operator to select a particular index.

    collection.within(latitude, longitude, radius).distance()

    This will add an attribute _distance to all documents returned, whichcontains the distance between the given point and the document in meters.

    collection.within(latitude, longitude, radius).distance(name)

    This will add an attribute name to all documents returned, whichcontains the distance between the given point and the document in meters.

    Note: this method is not yet supported by the RocksDB storage engine.

    Note: the within simple query function is deprecated as of ArangoDB 2.6.The function may be removed in future versions of ArangoDB. The preferredway for retrieving documents from a collection using the within operator isto use the AQL WITHIN function in an AQL query as follows:

    1. FOR doc IN WITHIN(@@collection, @latitude, @longitude, @radius, @distanceAttributeName)
    2. RETURN doc

    Examples

    To find all documents within a radius of 2000 km use:

    1. arangosh> for (var i = -90; i <= 90; i += 10) {
    2. ........> for (var j = -180; j <= 180; j += 10) {
    3. ........> db.geo.save({ name : "Name/" + i + "/" + j, loc: [ i, j ] }); } }
    4. arangosh> db.geo.within(0, 0, 2000 * 1000).distance().toArray();
    5. [
    6. {
    7. "distance" : 0,
    8. "_id" : "geo/5518",
    9. "_key" : "5518",
    10. "_rev" : "_ZHpYUre--H",
    11. "loc" : [
    12. 0,
    13. 0
    14. ],
    15. "name" : "Name/0/0"
    16. },
    17. {
    18. "distance" : 1111949.2664455874,
    19. "_id" : "geo/5407",
    20. "_key" : "5407",
    21. "_rev" : "_ZHpYUr---D",
    22. "loc" : [
    23. -10,
    24. 0
    25. ],
    26. "name" : "Name/-10/0"
    27. },
    28. {
    29. "distance" : 1111949.2664455874,
    30. "_id" : "geo/5521",
    31. "_key" : "5521",
    32. "_rev" : "_ZHpYUri--_",
    33. "loc" : [
    34. 0,
    35. 10
    36. ],
    37. "name" : "Name/0/10"
    38. },
    39. {
    40. "distance" : 1111949.2664455874,
    41. "_id" : "geo/5629",
    42. "_key" : "5629",
    43. "_rev" : "_ZHpYUsC--F",
    44. "loc" : [
    45. 10,
    46. 0
    47. ],
    48. "name" : "Name/10/0"
    49. },
    50. {
    51. "distance" : 1111949.2664455874,
    52. "_id" : "geo/5515",
    53. "_key" : "5515",
    54. "_rev" : "_ZHpYUre--F",
    55. "loc" : [
    56. 0,
    57. -10
    58. ],
    59. "name" : "Name/0/-10"
    60. },
    61. {
    62. "distance" : 1568520.556798576,
    63. "_id" : "geo/5410",
    64. "_key" : "5410",
    65. "_rev" : "_ZHpYUr---F",
    66. "loc" : [
    67. -10,
    68. 10
    69. ],
    70. "name" : "Name/-10/10"
    71. },
    72. {
    73. "distance" : 1568520.556798576,
    74. "_id" : "geo/5632",
    75. "_key" : "5632",
    76. "_rev" : "_ZHpYUsC--H",
    77. "loc" : [
    78. 10,
    79. 10
    80. ],
    81. "name" : "Name/10/10"
    82. },
    83. {
    84. "distance" : 1568520.556798576,
    85. "_id" : "geo/5404",
    86. "_key" : "5404",
    87. "_rev" : "_ZHpYUr---B",
    88. "loc" : [
    89. -10,
    90. -10
    91. ],
    92. "name" : "Name/-10/-10"
    93. },
    94. {
    95. "distance" : 1568520.556798576,
    96. "_id" : "geo/5626",
    97. "_key" : "5626",
    98. "_rev" : "_ZHpYUsC--D",
    99. "loc" : [
    100. 10,
    101. -10
    102. ],
    103. "name" : "Name/10/-10"
    104. }
    105. ]

    Hide execution results

    1. arangosh> for (var i = -90; i <= 90; i += 10) {
    2. ........> for (var j = -180; j <= 180; j += 10) {
    3. arangosh> db.geo.within(0, 0, 2000 * 1000).distance().toArray();

    Show execution results

    ensures that a geo index existscollection.ensureIndex({ type: "geo", fields: [ "location" ] })

    The index does not provide a unique option because of its limited usability.It would prevent identical coordinates from being inserted only, but even aslightly different location (like 1 inch or 1 cm off) would be unique again andnot considered a duplicate, although it probably should. The desired thresholdfor detecting duplicates may vary for every project (including how to calculatethe distance even) and needs to be implemented on the application layer as needed.You can write a Foxx service for this purpose and make useof the AQL to find nearbycoordinates supported by a geo index.