3.3.8 MERGE语句

MERGE语句可以确保图数据库中存在某个特定的模式。如果该模式不存在,则创建它。

3.3.8.1 简介

MERGE或者匹配已存在的节点并绑定到它,或者创建新的节点然后绑定到它。它有点像MATCH和CREATE的组合。通过这种方式可以确保你指定的某个数据存在数据库中。例如,可以指定图中必须包含一个特定name的user节点。如果不存在特定name的user节点,那么就会创建一个。

当在整个模式上使用MERGE时,要么是整个模式匹配到,要么是整个模式被创建。MERGE不能部分地应用于模式,如果希望部分匹配,可以将模式拆分为多个MERGE语句。

MERGE图例如图3-11所示。

图3-11 MERGE图例

3.3.8.2 MERGE节点

1.合并带标签的节点

下面的例子合并给定标签的节点。

查询:

因为没有包含Critic标签的节点,所以在数据库创建了新节点。

结果:

2.合并带多个属性的单个节点

合并有多个属性但并不是所有属性都匹配到已存在节点的单个节点。

查询:

在数据库创建了名为Charlie Sheen的新节点,因为没有匹配到所有属性都吻合的节点。

结果:

3.合并同时指定标签和属性的节点

合并单个节点,要求它的标签和属性都能匹配到已存在的节点。

查询:

匹配到Michael Douglas节点,同时返回它的name和bornIn属性。

结果:

4.合并属性来自已存在节点的单个节点

当每个绑定节点的属性p来自一个节点集时,如果p存在重复,创建的时候只会创建一次。

查询:

本例中创建了三个City节点,它们的name属性分别为New York、Ohio和New Jersey。

注意:尽管MATCH匹配的结果总有三个节点的bornIn属性值都为New York,但只创建了一个New York节点。因为第一次匹配的时候,New York未匹配到,因此创建了一个。然后,新创建的New York被第二个和第三个匹配到了。

结果:

3.3.8.3 MERGE在CREATE和MATCH中的使用

1.MERGE与CREATE搭配

检查节点是否存在,如果不存在,则创建它并设置属性。

查询:

本查询创建了keanu节点,并将created属性设置为创建时的时间戳。

结果:

2.MERGE与MATCH搭配

匹配节点,并在找到的节点上设置属性。

查询:

本查询找到所有的Person节点,并设置found属性为true,然后返回它们。

结果:

3.MERGE与CREATE和MATCH同时使用

检查节点是否存在,如果不存在,则创建它并设置属性。

查询:

本查询创建keanu节点并设置created属性值为创建时的时间戳。如果keanu已经存在,将为它设置一个新属性lastSeen。也就是说,当keanu不存在时,创建后的keanu节点将没有lastSeen属性。

结果:

4.利用MERGE和MATCH设置多属性

如果需要设置多个属性,将它们简单地以逗号分开即可。

查询:

结果:

3.3.8.4 MERGE关系

MERGE可用于匹配或者创建关系。

查询:

因为Charlie Sheen参演了Wall Street,所以找到已存的关系并返回。

注意:使用MERGE去匹配或者创建关系时,必须至少指定一个绑定的节点。

结果:

1.合并多个关系

当MERGE应用于整个模式时,要么全部匹配上,要么全部新创建。

查询:

在本例中,Oliver Stone和Rob Reiner未一起工作过。当试图在其之间合并一个电影连接时,Neo4j不会使用任何已存在的电影,而是创建一个新的movie节点。

结果:

2.合并无方向关系

MERGE也可以用于合并无方向的关系。当创建关系时,它将选择一个任意的方向。

查询:

因为Charlie Sheen和Oliver Stone相互不认识,所以MERGE查询将在他们之间创建一个KNOWS关系。创建的关系的方向是任意的。

结果:

3.合并已存在两节点之间的关系

MERGE可用于连接前面的MATCH和MERGE语句,在两个绑定的节点m和n上创建一个关系。m节点是MATCH语句返回的,而n节点是前面的MERGE语句创建或者匹配到的。

查询:

这个例子来自3.3.8节。第二个MERGE在每个人和他的bornIn属性对应的城市之间创建了一个BORN_IN关系。Charlie Sheen、Rob Reiner和Oliver Stone与同一个城市节点(New York)都有一个BORIN_IN关系。

结果:

4.合并一个已存在节点和一个合并的节点之间的关系

MERGE能够同时创建一个新节点n和一个已存在节点m与n之间的关系。

查询:

在本例中,MERGE未匹配到,这里没有标签为Chauffeur的节点和HAS_CHAUFFUR关系。MERGE创建了5个带有Chauffeur标签的节点,每个节点的包含一个name属性,属性的值来自每个匹配到的Person节点的chauffeurName属性的值。MERGE同时还在每个Person节点与新创建的Chauffeur节点之间创建了一个HAS_CHAUFFEUR关系。

结果:

3.3.8.5 用MERGE的唯一性约束

当使用的模式涉及唯一性约束时,Cypher可以通过MERGE来防止获取相冲突的结果。在这种情况下,至多有一个节点匹配该模式。例如,给定两个唯一性约束:Person(id)和:Person(ssn),如果存在两个不同的节点分别是id为12和ssn为437或者只有一个节点有其中一个属性,那么MERGE (n:Person {id: 12, ssn: 437})这样的查询将失败。

下面的例子分别在Person的name和role属性上创建一个唯一性约束。

如果节点未找到,则使用唯一性约束创建该节点。

查询:

本查询创建了laurence节点。如果laurence已经存在,MERGE则仅匹配已经存在的节点。

结果:

使用唯一性约束匹配已存在的节点。

查询:

oliver节点已经存在了,因此MERGE只是匹配它而不创建。

结果:

1.唯一性约束与部分匹配

当只有部分匹配时,使用唯一性约束合并将失败。

查询:

这里有一个唯一匹配到的name为Michael Douglas的节点,但没有具有唯一的role属性为Gordon Gekko的节点,因此MERGE匹配失败。

错误消息:

2.唯一性约束与匹配冲突

当有匹配的冲突结果时,使用MERGE唯一性约束将失败。

查询:

错误消息:

3.3.8.6 使用map参数

MERGE不支持像CREATE节点时那样使用map参数。要在MERGE中使用map参数,需要显式地使用希望用到的属性。如下例所示。

参数:

查询:

结果: