Neo4j Cypher:列出边缘

时间:2017-01-22 20:18:27

标签: neo4j cypher

以此数据为例:

CREATE
(p1:Person {name:"p1"}),
(p2:Person {name:"p2"}),
(p3:Person {name:"p3"}),
(p4:Person {name:"p4"}),
(p5:Person {name:"p5"}),
(p1)-[:KNOWS]->(p2),
(p1)-[:KNOWS]->(p3),
(p1)-[:KNOWS]->(p4),
(p5)-[:KNOWS]->(p3),
(p5)-[:KNOWS]->(p4)

我想获得p1和p5之间的共同关系:

MATCH (p1:Person {name:"p1"})-[r1:KNOWS]-(p:Person)-[r2:KNOWS]-(p5:Person {name:"p5"})
RETURN p, p1, p5

返回4个节点:p1,p3,p4,p5和4个边。

我的目标是将方向边缘作为表格行:from和to。所以这似乎有效:

MATCH (p1:Person {name:"p1"})-[r1:KNOWS]-(p:Person)-[r2:KNOWS]-(p5:Person {name:"p5"})
RETURN startNode(r1).name AS from, endNode(r1).name AS to
UNION
MATCH (p1:Person {name:"p1"})-[r1:KNOWS]-(p:Person)-[r2:KNOWS]-(p5:Person {name:"p5"})
RETURN startNode(r2).name AS from, endNode(r2).name AS to

结果是一张表:

from | to
-----|----
p1   | p3
p1   | p4
p5   | p3
p5   | p4

我的问题是:

  • 这是对的吗?
  • 这是最好的方法吗?我的意思是当有数千个节点时的性能。
  • 如果我想要3个人的共同节点怎么办?

1 个答案:

答案 0 :(得分:2)

检查效果的最佳方法是PROFILE您的查询。

  

这是对的吗?

我不确定你为什么要使用UNION,你可以轻松地使用路径检查:

PROFILE MATCH (p1:Person {name:"p1"}), (p5:Person {name:"p5"})
MATCH path=(p1)-[*..2]-(p5)
UNWIND rels(path) AS r
RETURN startNode(r).name AS from, endNode(r).name AS to
  

这是最好的方法吗?我的意思是当有数千个节点时的性能。

通常,您将首先使用单个查找匹配所需路径的起始节点和结束节点(确保在Person节点的标签/属性对上有索引/约束)。 根据您的图形程度,这可能是一个广泛的操作,您可以通过限制路径*..15的最大深度来微调。

  

如果我想要3个人的共同节点怎么办?

根据图表的大小,有多种方式:

a)如果没有太多节点:

匹配3个节点,找到至少有一个连接到ALL 3的人:

PROFILE MATCH (p:Person) WHERE p.name IN ["p1","p4","p3"]
WITH collect(p) AS persons
MATCH (p:Person) WHERE ALL(x IN persons WHERE EXISTS((x)--(p)))
RETURN p
b)一些调整,假设一个公共将直接连接到3

中的第一个节点
PROFILE MATCH (p:Person) WHERE p.name IN ["p1","p4","p3"]
WITH collect(p) AS persons
WITH persons, persons[0] as p
MATCH (p)-[:KNOWS]-(other)
WHERE ALL (x IN persons WHERE EXISTS((x)--(other)))
RETURN other

c)如果您需要多个深度路径中的公共区域:

PROFILE MATCH (p:Person) WHERE p.name IN ["p1","p4","p3"]
WITH collect(p) AS persons
WITH persons, persons[0] as p1, persons[1] as p2
MATCH path=(p1)-[*..15]-(p2)
WHERE ANY(x IN nodes(path) WHERE x = persons[2])
UNWIND rels(path) AS commonRel
WITH distinct commonRel AS r
RETURN startNode(r) AS from, endNode(r) AS to

我建议您增加图表并尝试/调整用例