Cypher:没有循环的所有路径

Ste*_*fan 2 neo4j cypher

我无法在没有循环的情况下获得节点之间的所有可能路径.我用的是neo4j 3.0.4.我准备了一个例子,但首先是一个简短的解释.我有从A到Z的节点.这些节点可以以各种方式连接.我想获得没有循环的所有可能路径,这意味着不会多次访问特定节点.

这里的例子如下:

CREATE (newNode {name:'A'})
RETURN newNode;

CREATE (newNode {name:'B'})
RETURN newNode;

CREATE (newNode {name:'C'})
RETURN newNode;

CREATE (newNode {name:'D'})
RETURN newNode;

CREATE (newNode {name:'E'})
RETURN newNode;

CREATE (newNode {name:'Z'})
RETURN newNode;


MATCH (n1), (n2)
WHERE n1.name = 'A' AND n2.name = 'B'
CREATE
    (n1)-[r:CONNECTED_TO]->(n2)
RETURN n1, n2, r;

MATCH (n1), (n2)
WHERE n1.name = 'A' AND n2.name = 'C'
CREATE
    (n1)-[r:CONNECTED_TO]->(n2)
RETURN n1, n2, r;

MATCH (n1), (n2)
WHERE n1.name = 'B' AND n2.name = 'C'
CREATE
    (n1)-[r:CONNECTED_TO]->(n2)
RETURN n1, n2, r;

MATCH (n1), (n2)
WHERE n1.name = 'C' AND n2.name = 'D'
CREATE
    (n1)-[r:CONNECTED_TO]->(n2)
RETURN n1, n2, r;

MATCH (n1), (n2)
WHERE n1.name = 'D' AND n2.name = 'E'
CREATE
    (n1)-[r:CONNECTED_TO]->(n2)
RETURN n1, n2, r;

MATCH (n1), (n2)
WHERE n1.name = 'E' AND n2.name = 'Z'
CREATE
    (n1)-[r:CONNECTED_TO]->(n2)
RETURN n1, n2, r;

MATCH (n1), (n2)
WHERE n1.name = 'D' AND n2.name = 'Z'
CREATE
    (n1)-[r:CONNECTED_TO]->(n2)
RETURN n1, n2, r;

MATCH (n1), (n2)
WHERE n1.name = 'D' AND n2.name = 'A'
CREATE
    (n1)-[r:CONNECTED_TO]->(n2)
RETURN n1, n2, r;

MATCH (n1), (n2)
WHERE n1.name = 'B' AND n2.name = 'A'
CREATE
    (n1)-[r:CONNECTED_TO]->(n2)
RETURN n1, n2, r;


MATCH p=(from{name:'A'}), (to{name:'Z'}), 
path = (from)-[r*]->(to)
RETURN path
Run Code Online (Sandbox Code Playgroud)

如果我运行最后一个查询,我将得到类似A-> B-> A-> C-> D-> Z的路径.我想避免这个循环A-> B-> A. allShortestPaths对我不起作用,因为它只提供跳数最少的路径.但我希望所有路径都没有循环,跳数不相关.由于查询非常昂贵,因此有必要限制结果或路径长度.

path = (from)-[r*20]->(to)
Run Code Online (Sandbox Code Playgroud)

但这不是避免循环的解决方案,因为它们也可能在短路径中发生.

编辑1:好的,现在我想出一个可能的解决方案:

MATCH (from{name:'A'}), (to{name:'Z'}), 
path = (from)-[:CONNECTED_TO*]->(to)
WHERE NONE (n IN NODES(path) WHERE SIZE(FILTER(x IN NODES(path) WHERE n = x))> 1)
RETURN path, LENGTH(path) as length
ORDER BY length;
Run Code Online (Sandbox Code Playgroud)

这个查询似乎有效,但我认为它非常昂贵.有人能提供更好的解决方案吗?

Tor*_*man 7

如果将其更改为此过滤器,则过滤器会稍微失败:

WHERE ALL(x IN NODES(path) WHERE SINGLE(y IN NODES(path) WHERE y = x))
Run Code Online (Sandbox Code Playgroud)

但我不相信你会找到一种从根本上更有效的方式.当您的问题包含"所有路径"并且您的示例具有无限关系时,通常您的选项非常有限:)

  • 顺便说一下,既然你对'apoc`感到满意,那么在3.1版中使用用户定义的函数会更容易:你的过滤器只会变成`WHERE size(apoc.coll.toSet(NODES(path))=大小(节点(路径))`.如果你回顾[历史](http://stackoverflow.com/questions/13767748/returning-only-simple-paths-in-neo4j-cypher-query),你会发现这是一个棘手的问题,但它肯定会得到更好. (3认同)