我在使用2个可选路径从图表中选择数据时遇到问题。假设节点A,B,C,其中A与B和C具有可选关系。
如果我查询
match (a:A) where a.xx = XX optional match (a:A)-->(b:B) return ...
或
match (a:A) where a.xx = XX optional match (a:A)-->(c:C) return ...
一切都按预期工作。
如果我结合2:
match (a:A) where a.xx = XX
optional match (a:A)-->(b:B)
optional match (a:A)-->(c:C)
return ...
然后我只得到(在很长的查询时间之后)一个未知错误。
返回选择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 ...
uid是唯一的索引id,然后查询返回所需的结果。 但是它运行得非常慢(如果uid是索引,则约为60秒,如果uid具有唯一约束,则约为40秒) 数据集不是我称之为巨大的东西:6500,b 86和c 90000条目。
答案 0 :(得分:7)
鉴于您已经匹配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
可以更好地表达:
MATCH (a:A) WHERE a.xx = XX
OPTIONAL MATCH (a)-->(b:B)
OPTIONAL MATCH (a)-->(c:C)
这看起来非常接近你最初的例子,但没有理由让它表现糟糕。如果你可以在关系匹配上输入一个类型,它会表现得更好:
MATCH (a:A) WHERE a.xx = XX
OPTIONAL MATCH (a)-[:REL]->(b:B)
OPTIONAL MATCH (a)-[:REL]->(c:C)
请注意,在将已经绑定的节点带入OPTIONAL MATCH子句时,您不需要重新标记它们。
对于初始匹配,您应该使用任何属性的索引:
CREATE INDEX ON :A(xx)
您可以在console中尝试使用此功能:
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
答案 1 :(得分:3)
问题是两个可选匹配会创建一个交叉产品,因此您希望将基数降低到第二个基数,即
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`
答案 2 :(得分:0)
是的,您可以使用多个可选匹配。例如,在console.neo4j.org中:
MATCH (n:Crew)-[r:KNOWS]-(m)
OPTIONAL
MATCH (n:Crew)-[r:KNOWS]-(b)
OPTIONAL
MATCH (n:Crew)-[r:KNOWS]-(c)
RETURN n,b,c