How to eliminate all paths that pass through particular document or vertex while during Graph Traversal in ArangoDB

两盒软妹~` 提交于 2019-12-25 01:30:37

问题


I am trying to do a graph traversal here

I created two collections in ArangoDB, a document collection "Node" and an edge collection "Path". All my nodes have a name attribute (labels) and are connected by edges (lines) as shown in above illustration.

I tried below query to find paths that end with an end or error node:

FOR v, e, p IN 1..10 OUTBOUND 'Node/start_0' Path     
OPTIONS { bfs: true}     
FILTER (v.name == "end" OR v.name == "error")     
RETURN CONCAT_SEPARATOR(' - ', p.vertices[*].name)

The above query works as expected and returns me two paths:

["start - decide - execute1 - error"
 "start - decide - execute2 - end"]

But I am exploring how to eliminate all corresponding paths that pass through a particular node. For example, I want to eliminate all paths that pass through execute1. I tried this query:

 FOR v, e, p IN 1..10 OUTBOUND 'Node/start_0' Path     
 OPTIONS { bfs: true}     
 FILTER ((v.name == "end" OR v.name == "error") AND v.name != "execute1")     
 RETURN CONCAT_SEPARATOR(' - ', p.vertices[*].name)

But it doesn't work - it still returns me the two paths.

Can any one help me on how to reframe this query to make it return only one path, i.e. "start - decide - execute2 - end"?


回答1:


Your traversal has a variable depth of 1..10, which will find the followings paths:

  1. start - decide
  2. start - decide - execute1
  3. start - decide - execute2
  4. start - decide - execute1 - error
  5. start - decide - execute2 - end

Note how the paths with one hop (1) and two hops (2, 3) are returned as well. They are within one to ten hops. Your expectation might have been that only leaf nodes (4, 5) would be emitted by the traversal. It gives you all five paths however.

Your name attribute FILTER conditions are tested against v, which represents the last vertex of each of these paths.

  • "decide" is not equal to "end" or "error", so path 1 is filtered out.
  • "execute1" and "execute2" are not equal to "end" or "error", so paths 2 and 3 are filtered out as well.
  • "error" and "end" are equal to either of these values, but they also fulfill the condition != "execute1" - you are testing against the stop nodes and not all the nodes on the path here, so the behavior is correct but not what you want

Your options are:

  • filter out all paths which contain a vertex with name "execute1":
    FILTER p.vertices[*].name NONE == "execute1" AND v.name IN ["end", "error"]
  • don't let the traverser go past "execute1" using PRUNE (available since v3.4.5 and v3.5.0):
    PRUNE v.name == "execute1" … FILTER v.name IN ["end", "error"]
  • don't let the traverser go past "execute1", "end" or "error" (optimization for above query):
    PRUNE v.name IN ["execute1", "end", "error"] … FILTER v.name IN ["end", "error"]

Note that PRUNE will include the vertex for which the conditions are true, i.e. path 2 is discovered, but then filtered out by the FILTER conditions. PRUNE alone does not filter path 2 out. It will prevent the traversal to continue from "execute1" however, which means path 4 will not be discovered. FILTER removes the paths 1, 2 and 3 from the result, leaving only path 5.

Also note that the PRUNE clause must be placed before OPTIONS!

FOR v, e, p IN 1..10 OUTBOUND 'Node/start_0' Path
PRUNE v.name IN ["execute1", "end", "error"]
OPTIONS { bfs: true }
FILTER v.name IN ["end", "error"]
RETURN CONCAT_SEPARATOR(' - ', p.vertices[*].name)

Result: [ "start - decide - execute2 - end" ]

Docs: Pruning in Graph Traversals



来源:https://stackoverflow.com/questions/57722577/how-to-eliminate-all-paths-that-pass-through-particular-document-or-vertex-while

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!