以此数据为例:
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
我的问题是:
答案 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
我建议您增加图表并尝试/调整用例