From a30a93aa3f7cead1646e4266a25ff608dee263ac Mon Sep 17 00:00:00 2001 From: Wilfried Goesgens Date: Thu, 30 Aug 2018 19:22:13 +0200 Subject: [PATCH] fix example, so geo indices are actually used (#6305) --- .../AQL/Examples/CombiningGraphTraversals.md | 113 +++++++++++------- .../COMBINING_GRAPH_01_create_graph.generated | 32 ----- .../COMBINING_GRAPH_02_combine.generated | 85 ------------- .../COMBINING_GRAPH_02_show_geo.generated | 17 +++ .../COMBINING_GRAPH_03_combine_let.generated | 8 -- .../COMBINING_GRAPH_03_explain_geo.generated | 39 ++++++ .../COMBINING_GRAPH_04_combine.generated | 37 ++++++ .../COMBINING_GRAPH_05_combine_let.generated | 34 ++++++ ...d => COMBINING_GRAPH_06_cleanup.generated} | 0 .../@arangodb/graph-examples/example-graph.js | 37 +++--- 10 files changed, 217 insertions(+), 185 deletions(-) delete mode 100644 Documentation/Examples/COMBINING_GRAPH_02_combine.generated create mode 100644 Documentation/Examples/COMBINING_GRAPH_02_show_geo.generated delete mode 100644 Documentation/Examples/COMBINING_GRAPH_03_combine_let.generated create mode 100644 Documentation/Examples/COMBINING_GRAPH_03_explain_geo.generated create mode 100644 Documentation/Examples/COMBINING_GRAPH_04_combine.generated create mode 100644 Documentation/Examples/COMBINING_GRAPH_05_combine_let.generated rename Documentation/Examples/{COMBINING_GRAPH_04_cleanup.generated => COMBINING_GRAPH_06_cleanup.generated} (100%) diff --git a/Documentation/Books/AQL/Examples/CombiningGraphTraversals.md b/Documentation/Books/AQL/Examples/CombiningGraphTraversals.md index 1bf051bdde..68d0690441 100644 --- a/Documentation/Books/AQL/Examples/CombiningGraphTraversals.md +++ b/Documentation/Books/AQL/Examples/CombiningGraphTraversals.md @@ -9,68 +9,91 @@ We use [the city graph](../../Manual/Graphs/index.html#the-city-graph) and its g ![Cities Example Graph](../../Manual/Graphs/cities_graph.png) - @startDocuBlockInline COMBINING_GRAPH_01_create_graph @EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_01_create_graph} - ~addIgnoreCollection("germanHighway"); - ~addIgnoreCollection("germanCity"); - ~addIgnoreCollection("frenchHighway"); - ~addIgnoreCollection("frenchCity"); - ~addIgnoreCollection("internationalHighway"); var examples = require("@arangodb/graph-examples/example-graph.js"); var g = examples.loadGraph("routeplanner"); - var bonn=[7.0998, 50.7340]; - |db._query(`FOR startCity IN germanCity - | FILTER GEO_DISTANCE(@bonn, startCity) < @radius - | RETURN startCity`, - | { bonn: bonn, radius: 400000 } - ).toArray() + ~examples.dropGraph("routeplanner"); @END_EXAMPLE_ARANGOSH_OUTPUT @endDocuBlock COMBINING_GRAPH_01_create_graph 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. - @startDocuBlockInline COMBINING_GRAPH_02_combine - @EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_02_combine} - var bonn=[7.0998, 50.7340]; - |db._query(`FOR startCity IN germanCity - | FILTER GEO_DISTANCE(@bonn, startCity) < @radius - | FOR v, e, p IN 1..1 OUTBOUND startCity - | GRAPH 'routeplanner' - | RETURN {startcity: startCity._key, traversedCity: v}`, - | { bonn: bonn, radius: 400000 } - ).toArray(); - @END_EXAMPLE_ARANGOSH_OUTPUT - @endDocuBlock COMBINING_GRAPH_02_combine + @startDocuBlockInline COMBINING_GRAPH_02_show_geo + @EXAMPLE_AQL{COMBINING_GRAPH_02_show_geo} + @DATASET{routeplanner} + FOR startCity IN germanCity + FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius + RETURN startCity._key + @BV { + bonn: [7.0998, 50.7340], + radius: 400000 + } + @END_EXAMPLE_AQL + @endDocuBlock COMBINING_GRAPH_02_show_geo -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. +Lets revalidate that the geo indices are actually used: + + @startDocuBlockInline COMBINING_GRAPH_03_explain_geo + @EXAMPLE_AQL{COMBINING_GRAPH_03_explain_geo} + @DATASET{routeplanner} + @EXPLAIN{TRUE} + FOR startCity IN germanCity + FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius + RETURN startCity._key + @BV { + bonn: [7.0998, 50.7340], + radius: 400000 + } + @END_EXAMPLE_AQL + @endDocuBlock COMBINING_GRAPH_03_explain_geo + +And now combine this with a graph traversal: + + @startDocuBlockInline COMBINING_GRAPH_04_combine + @EXAMPLE_AQL{COMBINING_GRAPH_04_combine} + @DATASET{routeplanner} + 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} + @BV { + bonn: [7.0998, 50.7340], + radius: 400000 + } + @END_EXAMPLE_AQL + @endDocuBlock COMBINING_GRAPH_04_combine + +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: - @startDocuBlockInline COMBINING_GRAPH_03_combine_let - @EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_03_combine_let} - ~var bonn=[50.7340, 7.0998]; - |db._query(`FOR startCity IN germanCity - | FILTER GEO_DISTANCE(@bonn, startCity) < @radius - | LET oneCity = (FOR v, e, p IN 1..1 OUTBOUND startCity - | GRAPH 'routeplanner' RETURN v) - | return {startCity: startCity._key, connectedCities: oneCity}`, - | { bonn: bonn, radius: 400000 } - ).toArray(); - @END_EXAMPLE_ARANGOSH_OUTPUT - @endDocuBlock COMBINING_GRAPH_03_combine_let + @startDocuBlockInline COMBINING_GRAPH_05_combine_let + @EXAMPLE_AQL{COMBINING_GRAPH_05_combine_let} + @DATASET{routeplanner} + 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} + @BV { + bonn: [7.0998, 50.7340], + radius: 400000 + } + @END_EXAMPLE_AQL + @endDocuBlock COMBINING_GRAPH_05_combine_let Finally, we clean up again: - @startDocuBlockInline COMBINING_GRAPH_04_cleanup - @EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_04_cleanup} + @startDocuBlockInline COMBINING_GRAPH_06_cleanup + @EXAMPLE_ARANGOSH_OUTPUT{COMBINING_GRAPH_06_cleanup} ~var examples = require("@arangodb/graph-examples/example-graph.js"); + ~var g = examples.loadGraph("routeplanner"); examples.dropGraph("routeplanner"); - ~removeIgnoreCollection("germanHighway"); - ~removeIgnoreCollection("germanCity"); - ~removeIgnoreCollection("frenchHighway"); - ~removeIgnoreCollection("frenchCity"); - ~removeIgnoreCollection("internationalHighway"); @END_EXAMPLE_ARANGOSH_OUTPUT - @endDocuBlock COMBINING_GRAPH_04_cleanup + @endDocuBlock COMBINING_GRAPH_06_cleanup diff --git a/Documentation/Examples/COMBINING_GRAPH_01_create_graph.generated b/Documentation/Examples/COMBINING_GRAPH_01_create_graph.generated index 88d2301026..6472fb4682 100644 --- a/Documentation/Examples/COMBINING_GRAPH_01_create_graph.generated +++ b/Documentation/Examples/COMBINING_GRAPH_01_create_graph.generated @@ -1,34 +1,2 @@ arangosh> var examples = require("@arangodb/graph-examples/example-graph.js"); arangosh> var g = examples.loadGraph("routeplanner"); -arangosh> var bonn=[7.0998, 50.7340]; -arangosh> db._query(`FOR startCity IN germanCity -........> FILTER GEO_DISTANCE(@bonn, startCity) < @radius -........> RETURN startCity`, -........> { bonn: bonn, radius: 400000 } -........> ).toArray() -[ - { - "_key" : "Cologne", - "_id" : "germanCity/Cologne", - "_rev" : "_XWXBCQG--B", - "population" : 1000000, - "isCapital" : false, - "type" : "Point", - "coordinates" : [ - 6.9528, - 50.9364 - ] - }, - { - "_key" : "Hamburg", - "_id" : "germanCity/Hamburg", - "_rev" : "_XWXBCQG--D", - "population" : 1000000, - "isCapital" : false, - "type" : "Point", - "coordinates" : [ - 10.0014, - 53.5653 - ] - } -] diff --git a/Documentation/Examples/COMBINING_GRAPH_02_combine.generated b/Documentation/Examples/COMBINING_GRAPH_02_combine.generated deleted file mode 100644 index 33116f8bcd..0000000000 --- a/Documentation/Examples/COMBINING_GRAPH_02_combine.generated +++ /dev/null @@ -1,85 +0,0 @@ -arangosh> var bonn=[7.0998, 50.7340]; -arangosh> db._query(`FOR startCity IN germanCity -........> FILTER GEO_DISTANCE(@bonn, startCity) < @radius -........> FOR v, e, p IN 1..1 OUTBOUND startCity -........> GRAPH 'routeplanner' -........> RETURN {startcity: startCity._key, traversedCity: v}`, -........> { bonn: bonn, radius: 400000 } -........> ).toArray(); -[ - { - "startcity" : "Cologne", - "traversedCity" : { - "_key" : "Lyon", - "_id" : "frenchCity/Lyon", - "_rev" : "_XWXBCQK--_", - "population" : 80000, - "isCapital" : false, - "type" : "Point", - "coordinates" : [ - 4.84, - 45.76 - ] - } - }, - { - "startcity" : "Cologne", - "traversedCity" : { - "_key" : "Paris", - "_id" : "frenchCity/Paris", - "_rev" : "_XWXBCQK--B", - "population" : 4000000, - "isCapital" : true, - "type" : "Point", - "coordinates" : [ - 2.3508, - 48.8567 - ] - } - }, - { - "startcity" : "Hamburg", - "traversedCity" : { - "_key" : "Cologne", - "_id" : "germanCity/Cologne", - "_rev" : "_XWXBCQG--B", - "population" : 1000000, - "isCapital" : false, - "type" : "Point", - "coordinates" : [ - 6.9528, - 50.9364 - ] - } - }, - { - "startcity" : "Hamburg", - "traversedCity" : { - "_key" : "Paris", - "_id" : "frenchCity/Paris", - "_rev" : "_XWXBCQK--B", - "population" : 4000000, - "isCapital" : true, - "type" : "Point", - "coordinates" : [ - 2.3508, - 48.8567 - ] - } - }, - { - "startcity" : "Hamburg", - "traversedCity" : { - "_key" : "Lyon", - "_id" : "frenchCity/Lyon", - "_rev" : "_XWXBCQK--_", - "population" : 80000, - "isCapital" : false, - "type" : "Point", - "coordinates" : [ - 4.84, - 45.76 - ] - } - } -] diff --git a/Documentation/Examples/COMBINING_GRAPH_02_show_geo.generated b/Documentation/Examples/COMBINING_GRAPH_02_show_geo.generated new file mode 100644 index 0000000000..643f56490c --- /dev/null +++ b/Documentation/Examples/COMBINING_GRAPH_02_show_geo.generated @@ -0,0 +1,17 @@ +@Q: + FOR startCity IN germanCity + FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius + RETURN startCity._key +@B +{ + "bonn": [ + 7.0998, + 50.734 + ], + "radius": 400000 +} +@R +[ + "Cologne", + "Hamburg" +] \ No newline at end of file diff --git a/Documentation/Examples/COMBINING_GRAPH_03_combine_let.generated b/Documentation/Examples/COMBINING_GRAPH_03_combine_let.generated deleted file mode 100644 index abc2fe9854..0000000000 --- a/Documentation/Examples/COMBINING_GRAPH_03_combine_let.generated +++ /dev/null @@ -1,8 +0,0 @@ -arangosh> db._query(`FOR startCity IN germanCity -........> FILTER GEO_DISTANCE(@bonn, startCity) < @radius -........> LET oneCity = (FOR v, e, p IN 1..1 OUTBOUND startCity -........> GRAPH 'routeplanner' RETURN v) -........> return {startCity: startCity._key, connectedCities: oneCity}`, -........> { bonn: bonn, radius: 400000 } -........> ).toArray(); -[ ] diff --git a/Documentation/Examples/COMBINING_GRAPH_03_explain_geo.generated b/Documentation/Examples/COMBINING_GRAPH_03_explain_geo.generated new file mode 100644 index 0000000000..208cfbdfba --- /dev/null +++ b/Documentation/Examples/COMBINING_GRAPH_03_explain_geo.generated @@ -0,0 +1,39 @@ +@Q: + FOR startCity IN germanCity + FILTER GEO_DISTANCE(@bonn, startCity.geometry) < @radius + RETURN startCity._key +@B +{ + "bonn": [ + 7.0998, + 50.734 + ], + "radius": 400000 +} +@R +Query String: + 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 */ + 5 CalculationNode 3 - LET #3 = startCity.`_key` /* attribute expression */ /* collections used: startCity : germanCity */ + 6 ReturnNode 3 - RETURN #3 + +Indexes used: + By Type Collection Unique Sparse Selectivity Fields Ranges + 7 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 + diff --git a/Documentation/Examples/COMBINING_GRAPH_04_combine.generated b/Documentation/Examples/COMBINING_GRAPH_04_combine.generated new file mode 100644 index 0000000000..a56b20c8c9 --- /dev/null +++ b/Documentation/Examples/COMBINING_GRAPH_04_combine.generated @@ -0,0 +1,37 @@ +@Q: + 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} +@B +{ + "bonn": [ + 7.0998, + 50.734 + ], + "radius": 400000 +} +@R +[ + { + "startcity": "Cologne", + "traversedCity": "Lyon" + }, + { + "startcity": "Cologne", + "traversedCity": "Paris" + }, + { + "startcity": "Hamburg", + "traversedCity": "Cologne" + }, + { + "startcity": "Hamburg", + "traversedCity": "Paris" + }, + { + "startcity": "Hamburg", + "traversedCity": "Lyon" + } +] \ No newline at end of file diff --git a/Documentation/Examples/COMBINING_GRAPH_05_combine_let.generated b/Documentation/Examples/COMBINING_GRAPH_05_combine_let.generated new file mode 100644 index 0000000000..be88724675 --- /dev/null +++ b/Documentation/Examples/COMBINING_GRAPH_05_combine_let.generated @@ -0,0 +1,34 @@ +@Q: + 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} +@B +{ + "bonn": [ + 7.0998, + 50.734 + ], + "radius": 400000 +} +@R +[ + { + "startCity": "Cologne", + "connectedCities": [ + "Lyon", + "Paris" + ] + }, + { + "startCity": "Hamburg", + "connectedCities": [ + "Cologne", + "Paris", + "Lyon" + ] + } +] \ No newline at end of file diff --git a/Documentation/Examples/COMBINING_GRAPH_04_cleanup.generated b/Documentation/Examples/COMBINING_GRAPH_06_cleanup.generated similarity index 100% rename from Documentation/Examples/COMBINING_GRAPH_04_cleanup.generated rename to Documentation/Examples/COMBINING_GRAPH_06_cleanup.generated diff --git a/js/common/modules/@arangodb/graph-examples/example-graph.js b/js/common/modules/@arangodb/graph-examples/example-graph.js index 9a29d1cc67..21419bbf18 100644 --- a/js/common/modules/@arangodb/graph-examples/example-graph.js +++ b/js/common/modules/@arangodb/graph-examples/example-graph.js @@ -111,37 +111,44 @@ var createRoutePlannerGraph = function () { _key: 'Berlin', population: 3000000, isCapital: true, - 'type': 'Point', - 'coordinates': [13.3833, 52.5167] - }); + geometry: { + 'type': 'Point', + 'coordinates': [13.3833, 52.5167] + }}); var cologne = g.germanCity.save({ _key: 'Cologne', population: 1000000, isCapital: false, - 'type': 'Point', - 'coordinates': [6.9528, 50.9364] - }); + geometry: { + 'type': 'Point', + 'coordinates': [6.9528, 50.9364] + }}); var hamburg = g.germanCity.save({ _key: 'Hamburg', population: 1000000, isCapital: false, - 'type': 'Point', - 'coordinates': [10.0014, 53.5653] - }); + geometry: { + 'type': 'Point', + 'coordinates': [10.0014, 53.5653] + }}); var lyon = g.frenchCity.save({ _key: 'Lyon', population: 80000, isCapital: false, - 'type': 'Point', - 'coordinates': [4.8400, 45.7600]}); + geometry: { + 'type': 'Point', + 'coordinates': [4.8400, 45.7600] + }}); var paris = g.frenchCity.save({ _key: 'Paris', population: 4000000, isCapital: true, - 'type': 'Point', - 'coordinates': [2.3508, 48.8567]}); - g.germanCity.ensureIndex({ type: "geo", fields: [ "coordinates" ], geoJson:true }); - g.frenchCity.ensureIndex({ type: "geo", fields: [ "coordinates" ], geoJson:true }); + geometry: { + 'type': 'Point', + 'coordinates': [2.3508, 48.8567] + }}); + g.germanCity.ensureIndex({ type: "geo", fields: [ "geometry" ], geoJson:true }); + g.frenchCity.ensureIndex({ type: "geo", fields: [ "geometry" ], geoJson:true }); g.germanHighway.save(berlin._id, cologne._id, {distance: 850}); g.germanHighway.save(berlin._id, hamburg._id, {distance: 400}); g.germanHighway.save(hamburg._id, cologne._id, {distance: 500});