Cypher:没有循环的所有路径

时间:2016-10-15 14:06:56

标签: 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

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

path = (from)-[r*20]->(to)

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

EDIT1: 好的,现在我想出了一个可能的解决方案:

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;

此查询似乎有效,但我认为它非常昂贵。有人可以提供更好的解决方案吗?

1 个答案:

答案 0 :(得分:7)

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

WHERE ALL(x IN NODES(path) WHERE SINGLE(y IN NODES(path) WHERE y = x))

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