一位同事编写了这样的代码:
match (a)-[r]->(b), (c) set c.x=y
逗号有什么作用?它只是MATCH的简写吗?
由于Cypher的ASCII艺术语法只允许您在一行中指定一个线性连接链,因此逗号至少部分地允许您指定可能分支的内容.例如:
MATCH (a)-->(b)<--(c), (b)-->(d)
这表示三个都连接到的节点b
(两个传入关系和一个传出关系.
如果匹配太长,逗号也可用于分隔行,如下所示:
MATCH (a)-->(b)<--(c), (c)-->(d)
显然这不是一个很长的路线,但这相当于:
MATCH (a)-->(b)<--(c)-->(d)
但一般来说,任何MATCH
语句都指定了您要搜索的模式.MATCH
形成图案的所有部分.在您的情况下,您实际上正在寻找两个未连接的模式((a)-[r]->(b)
和(c)
),因此Neo4j将找到两个模式的每个实例的每个组合,这可能非常昂贵.在Neo4j 2.3中你也可能会收到一个警告,这个查询会给你一个笛卡尔积.
但是,如果指定多个匹配项,则需要搜索不同的模式.所以,如果你这样做:
MATCH (a)-[r]->(b) MATCH (c)
从概念上讲,我认为它有点不同,但结果是一样的.不过,我知道这绝对是不同的OPTIONAL MATCH
.如果你这样做:
MATCH (a:Foo) OPTIONAL MATCH (a)-->(b:Bar), (a)-->(c:Baz)
您只能找到有Foo
节点未连接或连接到a Bar
和Baz
节点的实例.如果你这样做:
MATCH (a:Foo) OPTIONAL MATCH (a)-->(b:Bar) OPTIONAL MATCH (a)-->(c:Baz)
你会发现每一个Foo
节点,你会匹配零个或多个连接Bar
和Baz
独立节点.
编辑:
在评论中,Stefan Armbruster提出了一个很好的观点,即逗号也可用于将子模式分配给单个标识符.如:
MATCH path1=(a)-[:REL1]->(b), path2=(b)<-[:REL2*..10]-(c)
谢谢Stefan!
EDIT2:另见Mats的答案如下
Brian很好地解释了如何使用逗号来构建更大的子图模式,但是使用逗号和第二个MATCH
子句之间也有一个微妙但重要的区别.
考虑两个节点的简单图,它们之间有一个关系.查询
MATCH ()-->() MATCH ()-->() RETURN 1
将返回带有数字1的一行.MATCH
但是,用逗号替换第二行,并且根本不会返回任何行:
MATCH ()-->(), ()-->() RETURN 1
这是因为关系唯一性的概念.在每个MATCH
子句中,每个关系只会遍历一次.这意味着对于我的第二个查询,图中的一个关系将与第一个模式匹配,第二个模式将无法匹配任何内容,导致整个模式不匹配.我的第一个查询将匹配每个子句中的一个关系,从而为结果创建一行.
在Neo4j手册中阅读更多相关信息:http://neo4j.com/docs/stable/cypherdoc-uniqueness.html