Cypher:如何找到所有单节点不重复的链?

mda*_*alp 6 repeat neo4j chain cypher

我想找到从/到特定节点的所有路径。我希望路径中的每个节点只出现一次。

\n\n

例如,在这样的图中:

\n\n
(a)-[:REL]->(b)-[:REL]->(c)-[:REL]->(a)\n(a)-[:REL]->(e)-[:REL]->(f)-[:REL]->(a)\n(e)-[:REL]->(b)\n
Run Code Online (Sandbox Code Playgroud)\n\n

以图形方式:

\n\n
  e \xe2\x86\x92 b\n \xe2\x86\x99 \xe2\x86\x96 \xe2\x86\x97 \xe2\x86\x98\nf \xe2\x86\x92 a \xe2\x86\x90 c\n
Run Code Online (Sandbox Code Playgroud)\n\n

密码:

\n\n
CREATE (a { name:'A' })-[:REL]->(b {name:'B'})-[:REL]->(c { name:'C' })\n       -[:REL]->(a)-[:REL]->(e {name:'E'})-[:REL]->(f {name:'F'})-[:REL]->(a),\n       (e)-[:REL]->(b)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我希望从(a)开始的链研究能够回归

\n\n
(a)->(b)->(c)->(a)\n\n(a)->(e)->(f)->(a)\n\n(a)->(e)->(b)->(c)->(a)\n
Run Code Online (Sandbox Code Playgroud)\n\n

而从 (f) 开始仅返回

\n\n
(f)->(a)->(e)->(f)\n
Run Code Online (Sandbox Code Playgroud)\n\n

并不是

\n\n
(f)->(a)->(b)->(c)->(a)->(e)->(f)\n
Run Code Online (Sandbox Code Playgroud)\n\n

因为它两次通过节点 (a)。

\n\n

我尝试过:

\n\n
MATCH p=(a {name:'F'})-[:REL*1..]->(a) \nWHERE SINGLE(e1 IN TAIL(NODES(p)) WHERE SINGLE(e2 IN TAIL(NODES(p)) WHERE e1=e2))\nRETURN p\n
Run Code Online (Sandbox Code Playgroud)\n\n

但我没有得到结果。\n我能达到的最好结果是不重复此查询的起始节点:

\n\n
MATCH p=(a {name:'F'})-[:REL*1..]->(a) \nWHERE SINGLE(e IN TAIL(NODES(p)) WHERE e=a)\nRETURN p\n
Run Code Online (Sandbox Code Playgroud)\n\n

但显然这不是我想要的,因为它也会返回

\n\n
(f)->(a)->(b)->(c)->(a)->(e)->(f)\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是一条涉及节点 (a) 两次的路径。

\n\n

有人可以建议我一个解决方案吗?

\n\n

先感谢您。

\n\n

PS我使用的Neo4j版本是2.0

\n

Joh*_*k13 2

在前人的肩膀上,我想出了:

MATCH (a { name:'A' })
MATCH (a)-[p:REL]->(s)
WITH a, s
MATCH p = s-[r:REL*]->a
WITH [a] + nodes(p) AS ns
    WHERE ALL (n IN ns 
       WHERE 1=LENGTH(FILTER(m IN TAIL(ns) 
                             WHERE m = n)))
RETURN ns
Run Code Online (Sandbox Code Playgroud)

它利用 @FrobberOfBits 的想法来执行初始步骤,然后使用 Michael 链接的查询来对路径执行过滤。我认为 TAIL 可以被省略,如果你也省略了:

WITH [a] + nodes(p) AS ns    
Run Code Online (Sandbox Code Playgroud)

这将使查询可能如下:

MATCH (a { name:'A' })
MATCH (a)-[p:REL]->(s)
WITH a, s
MATCH p = s-[r:REL*]->a
WITH a, nodes(p) AS ns
WHERE ALL (n IN ns 
       WHERE 1=LENGTH(FILTER(m IN ns 
                             WHERE m = n)))
RETURN [a] + ns
Run Code Online (Sandbox Code Playgroud)

查询的复杂或至少稍微难以阅读的部分是与 ns 中的所有值“基本上”相ALL结合,通过与数组中的所有其他值进行比较来计算出现次数 ( ) 并完全过滤结果如果结果数组不包含单个元素 ( )。FILTER(WHERE ALL (n in ns)m IN ns WHERE m = n1=LENGTH

我在此处的控制台中添加了您的示例。