Cypher - 匹配两个不同的可能路径并且 return 两者
Cypher - matching two different possible paths and return both
我有一个数据集,我在这里表示为示例:
http://console.neo4j.org/?id=3dq78v
我想要做的是针对我图中的每个 Z 节点(该示例只有一个,但我有很多)我想捕获一组属性,涵盖所有相关的 A、B、C和 D 节点和关系。
我在尝试执行此操作时遇到了两个问题。第一个是 C 节点连接到 B 节点或 A 节点。其次,D 节点连接到 C 节点,但并不总是存在。
我希望输出一个看起来像这样的 table:
Z.prop | A.prop | B.prop | (A-B rel).prop | c.prop | (c-d rel).prop | d.prop
我尝试了很多使用 OPTIONAL MATCH 和使用 WITH 的组合,但我无法做到。我尝试使用 OPTIONAL MATCH 进行的所有操作都会找到该匹配项(如果存在),然后不允许我维护与该可选匹配项不匹配的项目(我意识到这是它应该做的)。如果有帮助,我可以分享我尝试过的更具体的查询。
任何见解都会很棒!
编辑:使用版本 Neo4j 2.0.3
编辑:更新控制台 link 并进行小的更正
这是我试过的查询。我知道为什么这不起作用,但也许你可以看到我的 'logic' 我希望可选匹配在找到一些匹配时不匹配时不删除节点。我想要那些不匹配的和做的。
MATCH (z:Z)-[:has]->(a:A)
OPTIONAL MATCH (a)-[:has*1..2]->(c:C)
OPTIONAL MATCH (a)-[:has]->(b:B)-[:CONTAINS]->(c)
OPTIONAL MATCH (c)-[cd:knows]->(d:D)
RETURN z.name, a.name, b.name, c.name, d.name, cd.score;
编辑:我想做的是使用下面 4 个查询的结果,但使用 1 个查询获得结果
#1
MATCH (z:Z)-[:has]->(a:A)
MATCH (A)-[mr:has]->(b:B)-[:has]->(c:C)
MATCH (c)-[ds:knows]->(d:d)
RETURN a.name, b.name, mr.order, c.name, d.name, ds.score;
#2
MATCH (z:Z)-[:has]->(a:A)
MATCH (A)-[mr:has]->(b:B)-[:has]->(c:C)
WHERE NOT (c)-[:knows]->(:d)
RETURN a.name, mr.order, b.name, c.name;
#3
MATCH (z:Z)-[:has]->(a:A)
MATCH (A)-[:has]->(c:C)
WHERE NOT (c)-[:knows]->(:d)
RETURN a.name, c.name;
#4
MATCH (z:Z)-[:has]->(a:A)
MATCH (A)-[:has]->(c:C)
MATCH (c)-[ds:knows]->(d:d)
RETURN a.name, c.name, d.name, ds.score;
这些并没有像我预期的那样工作,因为有些结果。例如,我期望查询 3 仅 return:
A2 C4 d4 8
A2 C4 d5 6
A2 C4 d6 9
编辑 - 我的目标是精确输出:
a.name mr.order b.name c.name d.name d.score
A1 1 B3
A1 2 B1 C2
A1 2 B1 C5
A1 2 B1 C1 d1 1
A1 2 B1 C1 d3 4
A1 2 B1 C1 d2 3
A2 1 B4
A2 2 B2 C3
A2 C4 d4 8
A2 C4 d5 6
A2 C4 d6 9
这与我要查找的 11 行中的 9 行匹配,它遗漏了包含 B3 和 B4 的行
MATCH (z:Z)-[:has]->(a:A)
WITH a, z
MATCH (a)-[*1..2]-(c:C)
OPTIONAL MATCH (a)-[mr:has]->(b:B)-[:has]-(c:C)
WITH a, b, c, z, mr
OPTIONAL MATCH (c)-[cd:knows]->(d:d)
RETURN z.name, a.name, mr.order, b.name, c.name, d.name, cd.score;
不完全确定你期望的输出是什么,但这个可能有用:
MATCH (z:Z)-[:has]->(a:A)
WITH a, z
MATCH (b:B), (a)-[*1..2]-(c:C)
WHERE (a)-[:has]->(b)-[:CONTAINS]->(c) OR (a)-[:has*1..2]->(c)
WITH a, b, c, z
OPTIONAL MATCH (c)-[cd:knows]->(d:d)
RETURN z.name, a.name, b.name, c.name, d.name, cd.score;
从那里你可以优化它。
编辑
添加后,我认为唯一可以实现的方法是使用两个查询的 UNION
MATCH (a:A)-[mr:has]->(b:B)
OPTIONAL MATCH (b)-->(c:C)
OPTIONAL MATCH (c)-[cd]->(d:d)
RETURN a.name, mr.order, b.name, c.name, d.name, cd.score
UNION
MATCH (a:A)-[mr:has]->(c:C)
OPTIONAL MATCH (c:C)-[cd]->(d:d)
OPTIONAL MATCH (b:B)-->(c:C)
RETURN a.name, mr.order, b.name, c.name, d.name, cd.score
请注意,在 UNION
之后的第二个查询中,OPTIONAL MATCH (b:B)-->(c:C)
只是为了使 UNION
成为可能,因为 Neo4j 不允许仅 return 一个空字符串而不是 b.name
。好消息是 UNION
将删除重复项,从而产生预期的结果。
a.name mr.order b.name c.name d.name cd.score
A1 1 B3
A1 2 B1 C5
A1 2 B1 C1 d1 1
A1 2 B1 C1 d2 4
A1 2 B1 C1 d3 3
A1 2 B1 C2
A2 1 B4
A2 2 B2 C3
A2 C4 d4 8
A2 C4 d5 6
A2 C4 d6 9
Showing 1 to 11 of 11 entries
查询耗时 9 毫秒,return编辑了 11 行。
我有一个数据集,我在这里表示为示例: http://console.neo4j.org/?id=3dq78v
我想要做的是针对我图中的每个 Z 节点(该示例只有一个,但我有很多)我想捕获一组属性,涵盖所有相关的 A、B、C和 D 节点和关系。
我在尝试执行此操作时遇到了两个问题。第一个是 C 节点连接到 B 节点或 A 节点。其次,D 节点连接到 C 节点,但并不总是存在。
我希望输出一个看起来像这样的 table:
Z.prop | A.prop | B.prop | (A-B rel).prop | c.prop | (c-d rel).prop | d.prop
我尝试了很多使用 OPTIONAL MATCH 和使用 WITH 的组合,但我无法做到。我尝试使用 OPTIONAL MATCH 进行的所有操作都会找到该匹配项(如果存在),然后不允许我维护与该可选匹配项不匹配的项目(我意识到这是它应该做的)。如果有帮助,我可以分享我尝试过的更具体的查询。
任何见解都会很棒!
编辑:使用版本 Neo4j 2.0.3 编辑:更新控制台 link 并进行小的更正
这是我试过的查询。我知道为什么这不起作用,但也许你可以看到我的 'logic' 我希望可选匹配在找到一些匹配时不匹配时不删除节点。我想要那些不匹配的和做的。
MATCH (z:Z)-[:has]->(a:A)
OPTIONAL MATCH (a)-[:has*1..2]->(c:C)
OPTIONAL MATCH (a)-[:has]->(b:B)-[:CONTAINS]->(c)
OPTIONAL MATCH (c)-[cd:knows]->(d:D)
RETURN z.name, a.name, b.name, c.name, d.name, cd.score;
编辑:我想做的是使用下面 4 个查询的结果,但使用 1 个查询获得结果
#1
MATCH (z:Z)-[:has]->(a:A)
MATCH (A)-[mr:has]->(b:B)-[:has]->(c:C)
MATCH (c)-[ds:knows]->(d:d)
RETURN a.name, b.name, mr.order, c.name, d.name, ds.score;
#2
MATCH (z:Z)-[:has]->(a:A)
MATCH (A)-[mr:has]->(b:B)-[:has]->(c:C)
WHERE NOT (c)-[:knows]->(:d)
RETURN a.name, mr.order, b.name, c.name;
#3
MATCH (z:Z)-[:has]->(a:A)
MATCH (A)-[:has]->(c:C)
WHERE NOT (c)-[:knows]->(:d)
RETURN a.name, c.name;
#4
MATCH (z:Z)-[:has]->(a:A)
MATCH (A)-[:has]->(c:C)
MATCH (c)-[ds:knows]->(d:d)
RETURN a.name, c.name, d.name, ds.score;
这些并没有像我预期的那样工作,因为有些结果。例如,我期望查询 3 仅 return:
A2 C4 d4 8
A2 C4 d5 6
A2 C4 d6 9
编辑 - 我的目标是精确输出:
a.name mr.order b.name c.name d.name d.score
A1 1 B3
A1 2 B1 C2
A1 2 B1 C5
A1 2 B1 C1 d1 1
A1 2 B1 C1 d3 4
A1 2 B1 C1 d2 3
A2 1 B4
A2 2 B2 C3
A2 C4 d4 8
A2 C4 d5 6
A2 C4 d6 9
这与我要查找的 11 行中的 9 行匹配,它遗漏了包含 B3 和 B4 的行
MATCH (z:Z)-[:has]->(a:A)
WITH a, z
MATCH (a)-[*1..2]-(c:C)
OPTIONAL MATCH (a)-[mr:has]->(b:B)-[:has]-(c:C)
WITH a, b, c, z, mr
OPTIONAL MATCH (c)-[cd:knows]->(d:d)
RETURN z.name, a.name, mr.order, b.name, c.name, d.name, cd.score;
不完全确定你期望的输出是什么,但这个可能有用:
MATCH (z:Z)-[:has]->(a:A)
WITH a, z
MATCH (b:B), (a)-[*1..2]-(c:C)
WHERE (a)-[:has]->(b)-[:CONTAINS]->(c) OR (a)-[:has*1..2]->(c)
WITH a, b, c, z
OPTIONAL MATCH (c)-[cd:knows]->(d:d)
RETURN z.name, a.name, b.name, c.name, d.name, cd.score;
从那里你可以优化它。
编辑
添加后,我认为唯一可以实现的方法是使用两个查询的 UNION
MATCH (a:A)-[mr:has]->(b:B)
OPTIONAL MATCH (b)-->(c:C)
OPTIONAL MATCH (c)-[cd]->(d:d)
RETURN a.name, mr.order, b.name, c.name, d.name, cd.score
UNION
MATCH (a:A)-[mr:has]->(c:C)
OPTIONAL MATCH (c:C)-[cd]->(d:d)
OPTIONAL MATCH (b:B)-->(c:C)
RETURN a.name, mr.order, b.name, c.name, d.name, cd.score
请注意,在 UNION
之后的第二个查询中,OPTIONAL MATCH (b:B)-->(c:C)
只是为了使 UNION
成为可能,因为 Neo4j 不允许仅 return 一个空字符串而不是 b.name
。好消息是 UNION
将删除重复项,从而产生预期的结果。
a.name mr.order b.name c.name d.name cd.score
A1 1 B3
A1 2 B1 C5
A1 2 B1 C1 d1 1
A1 2 B1 C1 d2 4
A1 2 B1 C1 d3 3
A1 2 B1 C2
A2 1 B4
A2 2 B2 C3
A2 C4 d4 8
A2 C4 d5 6
A2 C4 d6 9
Showing 1 to 11 of 11 entries
查询耗时 9 毫秒,return编辑了 11 行。