密码2中的多个OPTIONAL MATCH子句

ber*_*ert 5 pattern-matching neo4j cypher

我在使用2个可选路径从图表中选择数据时遇到问题.假设节点A,B,C,其中A与B和C具有可选关系.

如果我查询

match (a:A) where a.xx = XX optional match (a:A)-->(b:B) return ...
Run Code Online (Sandbox Code Playgroud)

要么

match (a:A) where a.xx = XX optional match (a:A)-->(c:C) return ...
Run Code Online (Sandbox Code Playgroud)

一切都按预期工作.

如果我结合2:

match (a:A) where a.xx = XX 
optional match (a:A)-->(b:B) 
optional match (a:A)-->(c:C) 
return ...
Run Code Online (Sandbox Code Playgroud)

然后我只得到(经过长时间的查询时间)一个未知的错误.

返回从a,b,c中选择属性,并使用限制来限制返回的数据量.是否不可能有多个可选匹配?

更新: 当我将查询更改为

match (a1:A) where a.xx = XX 
optional match (a2:A)-->(b:B) where a2.uid = a1.uid
optional match (a3:A)-->(c:C) where a3.uid = a1.uid
return ...
Run Code Online (Sandbox Code Playgroud)

如果uid是唯一的索引id,则查询返回所需的结果.它的运行速度非常慢(如果uid是索引,则为~60秒,如果uid具有唯一约束,则为〜40s)数据集不是我称之为巨大的数据集:6500,b 86和c 90000条目.

Joh*_*k13 8

鉴于你已经匹配A过一次,你为什么要重新匹配呢?

MATCH (a1:A) WHERE a.xx = XX 
OPTIONAL MATCH (a2:A)-->(b:B) WHERE a2.uid = a1.uid
OPTIONAL MATCH (a3:A)-->(c:C) WHERE a3.uid = a1.uid
Run Code Online (Sandbox Code Playgroud)

可以更好地表达:

MATCH (a:A) WHERE a.xx = XX 
OPTIONAL MATCH (a)-->(b:B)
OPTIONAL MATCH (a)-->(c:C)
Run Code Online (Sandbox Code Playgroud)

这看起来非常接近你最初的例子,但没有理由让它表现糟糕.如果你可以在关系匹配上放置一个类型,它会表现得更好:

MATCH (a:A) WHERE a.xx = XX 
OPTIONAL MATCH (a)-[:REL]->(b:B)
OPTIONAL MATCH (a)-[:REL]->(c:C)
Run Code Online (Sandbox Code Playgroud)

请注意,在将已经绑定的节点传送到OPTIONAL MATCH子句中时,您不需要重新标记它们.

对于初始匹配,您应该使用任何属性的索引:

CREATE INDEX ON :A(xx)
Run Code Online (Sandbox Code Playgroud)

您可以在控制台中尝试此操作以查看它是否正常工作:

MATCH (n:Crew)
OPTIONAL MATCH (n)-[:KNOWS]-m
OPTIONAL MATCH (n)-[:LOVES]-t
RETURN n AS Neo,COLLECT(m) AS knows, COLLECT(t) AS loves
Run Code Online (Sandbox Code Playgroud)


Mic*_*ger 5

问题是两个可选匹配创建了一个叉积,因此您希望在第二个匹配之前降低基数,即

create index on :A(xx);

MATCH (a:A) WHERE a.xx = XX 
OPTIONAL MATCH (a)-->(b:B) 
WITH a, collect(b) as b_nodes
OPTIONAL MATCH (a)-->(c:C) 
RETURN a, b_nodes, collect(c) as c_nodes`
Run Code Online (Sandbox Code Playgroud)