ArangoDB v3.8 reached End of Life (EOL) and is no longer supported.

This documentation is outdated. Please see the most recent version at docs.arangodb.com

Combining Graph Traversals

Finding the start vertex via a geo query

Our first example will locate the start vertex for a graph traversal via a geo index. We use the city graph and its geo indexes:

Cities Example Graph

arangosh> var examples = require("@arangodb/graph-examples/example-graph.js");
arangosh> var g = examples.loadGraph("routeplanner");
Show execution results
Hide execution results
(Empty output)

We search all german cities in a range of 400 km around the ex-capital Bonn: Hamburg and Cologne. We won’t find Paris since its in the frenchCity collection.

FOR startCity IN germanCity
    FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius
      RETURN startCity._key
Show query results
Hide query results
Bind Parameters:
{
  "bonn": [
    7.0998,
    50.734
  ],
  "radius": 400000
}
Result:
[
  "Cologne",
  "Hamburg"
]

Let’s revalidate that the geo indexes are actually used:

FOR startCity IN germanCity
    FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius
      RETURN startCity._key
Show query results
Hide query results
Bind Parameters:
{
  "bonn": [
    7.0998,
    50.734
  ],
  "radius": 400000
}
Explain:
Query String (119 chars, cacheable: true):
   FOR startCity IN germanCity
     FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius
       RETURN startCity._key
 

Execution plan:
 Id   NodeType          Est.   Comment
  1   SingletonNode        1   * ROOT
  7   IndexNode            3     - FOR startCity IN germanCity   /* geo index scan, projections: `_key` */    
  5   CalculationNode      3       - LET #3 = startCity.`_key`   /* attribute expression */   /* collections used: startCity : germanCity */
  6   ReturnNode           3       - RETURN #3

Indexes used:
 By   Name                      Type   Collection   Unique   Sparse   Selectivity   Fields           Ranges
  7   idx_1761718486746267653   geo    germanCity   false    true             n/a   [ `geometry` ]   (GEO_DISTANCE([ 7.0998, 50.734 ], startCity.`geometry`) < 400000)

Optimization rules applied:
 Id   RuleName
  1   move-calculations-up
  2   move-filters-up
  3   move-calculations-up-2
  4   move-filters-up-2
  5   geo-index-optimizer
  6   remove-unnecessary-calculations-2
  7   reduce-extraction-to-projection

Optimization rules with highest execution times:
 RuleName                                    Duration [s]
 geo-index-optimizer                              0.00001
 remove-redundant-calculations                    0.00000
 move-calculations-up                             0.00000
 reduce-extraction-to-projection                  0.00000
 move-filters-up                                  0.00000

42 rule(s) executed, 1 plan(s) created

And now combine this with a graph traversal:

FOR startCity IN germanCity
    FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius
      FOR v, e, p IN 1..1 OUTBOUND startCity
        GRAPH 'routeplanner'
      RETURN {startcity: startCity._key, traversedCity: v._key}
Show query results
Hide query results
Bind Parameters:
{
  "bonn": [
    7.0998,
    50.734
  ],
  "radius": 400000
}
Result:
[
  {
    "startcity": "Cologne",
    "traversedCity": "Lyon"
  },
  {
    "startcity": "Cologne",
    "traversedCity": "Paris"
  },
  {
    "startcity": "Hamburg",
    "traversedCity": "Cologne"
  },
  {
    "startcity": "Hamburg",
    "traversedCity": "Paris"
  },
  {
    "startcity": "Hamburg",
    "traversedCity": "Lyon"
  }
]

The geo index query returns us startCity (Cologne and Hamburg) which we then use as starting point for our graph traversal. For simplicity we only return their direct neighbours. We format the return result so we can see from which startCity the traversal came.

Alternatively we could use a LET statement with a subquery to group the traversals by their startCity efficiently:

FOR startCity IN germanCity
    FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius
      LET oneCity = (
        FOR v, e, p IN 1..1 OUTBOUND startCity
          GRAPH 'routeplanner' RETURN v._key
      )
        RETURN {startCity: startCity._key, connectedCities: oneCity}
Show query results
Hide query results
Bind Parameters:
{
  "bonn": [
    7.0998,
    50.734
  ],
  "radius": 400000
}
Result:
[
  {
    "startCity": "Cologne",
    "connectedCities": [
      "Lyon",
      "Paris"
    ]
  },
  {
    "startCity": "Hamburg",
    "connectedCities": [
      "Cologne",
      "Paris",
      "Lyon"
    ]
  }
]

Finally, we clean up again:

arangosh> examples.dropGraph("routeplanner");
Show execution results
Hide execution results
(Empty output)