From 2e840ee5d04c0f11bf551ba2de2d5e6e3139074c Mon Sep 17 00:00:00 2001 From: maxkernbach Date: Mon, 14 May 2018 10:35:31 +0200 Subject: [PATCH] Doc - New Example 'Multiple Path Search' (#5309) Issue #3545 --- .../Books/AQL/Examples/MultiplePaths.md | 42 ++++++++++++++++++ Documentation/Books/AQL/Examples/sp_graph.png | Bin 0 -> 16596 bytes Documentation/Books/AQL/SUMMARY.md | 1 + 3 files changed, 43 insertions(+) create mode 100644 Documentation/Books/AQL/Examples/MultiplePaths.md create mode 100644 Documentation/Books/AQL/Examples/sp_graph.png diff --git a/Documentation/Books/AQL/Examples/MultiplePaths.md b/Documentation/Books/AQL/Examples/MultiplePaths.md new file mode 100644 index 0000000000..af1862cee1 --- /dev/null +++ b/Documentation/Books/AQL/Examples/MultiplePaths.md @@ -0,0 +1,42 @@ +Multiple Path Search +==================== + +The shortest path algorithm can only determine one shortest path. +For example, if this is the full graph: + +![Example Graph](sp_graph.png) + +then a shortest path query from **A** to **C** may return the path `A -> B -> C` or `A -> D -> C`, but it's undefined which one (not taking edge weights into account here). + +You can use the efficient shortest path algorithm however, to determine the shortest path length: + +``` +RETURN LENGTH( + FOR v IN OUTBOUND + SHORTEST_PATH "verts/A" TO "verts/C" edges + RETURN v +) +``` + +The result is 3 for the example graph (includes the start vertex). Now, subtract 1 to get the edge count / traversal depth. You can run a pattern matching traversal to find all paths with this length (or longer ones by increasing the min and max depth). Starting point is **A** again, and a filter on the document ID of v (or p.vertices[-1]) ensures that we only retrieve paths that end at point **C**. + +The following query returns all parts with length 2, start vertex **A** and target vertex **C**: + +``` +FOR v, e, p IN 2..2 OUTBOUND "verts/A" edges + FILTER v._id == "verts/C" + RETURN CONCAT_SEPARATOR(" -> ", p.vertices[*]._key) +``` + +Output: + +``` +[ + "A -> B -> C", + "A -> D -> C" +] +``` + +A traversal depth of `3..3` would return `A -> E -> F -> C` and `2..3` all three paths. + +Note that two separate queries are required to compute the shortest path length and to do the pattern matching based on the shortest path length (minus 1), because min and max depth can't be expressions (they have to be known in advance, so either be number literals or bind parameters). diff --git a/Documentation/Books/AQL/Examples/sp_graph.png b/Documentation/Books/AQL/Examples/sp_graph.png new file mode 100644 index 0000000000000000000000000000000000000000..e3874e96845cf3f981e11f6cc2c9fff4905c3a15 GIT binary patch literal 16596 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