一、什么是 MERGE
语句?
MERGE
语句是 Cypher 中用于创建或匹配节点和关系的语句。
MERGE
会先检查数据库中是否存在匹配的节点或关系,如果存在,则返回该节点或关系;如果不存在,则创建新的节点或关系。MERGE
的行为类似于 SQL 中的INSERT ... ON DUPLICATE KEY UPDATE
或UPSERT
语法。
二、MERGE
的基本语法
MERGE (n:Label {propertyKey1: value1, propertyKey2: value2, ...})
语法说明:
MERGE
:指令,用于匹配或创建数据。n
:变量名,引用匹配到的或新创建的节点/关系。:Label
:节点或关系的标签或类型。{propertyKey: value}
:属性,用于指定匹配条件或创建新数据时的属性值。
三、MERGE
创建和匹配节点
3.1 MERGE 匹配或创建节点
MERGE (n:Person {name: 'Alice'})
RETURN n
- 如果
Person
节点中存在name = 'Alice'
,则匹配并返回该节点; - 如果
Alice
不存在,则创建新的Person
节点,并返回新创建的节点。
3.2 MERGE 创建无属性节点
MERGE (n:Person)
RETURN n
- 如果存在任意
Person
节点,则返回匹配的节点; - 如果不存在,则创建一个新的无属性
Person
节点。
3.3 MERGE 匹配多个属性
MERGE (n:Person {name: 'Alice', age: 30})
RETURN n
- 只有当
name = 'Alice'
且age = 30
的Person
节点同时存在时,才会匹配。 - 否则,创建一个新节点,
name
和age
属性将被设置。
3.4 MERGE 创建具有多个标签的节点
MERGE (n:Person:Employee {name: 'Alice'})
RETURN n
Person
和Employee
是双标签,MERGE
会检查带有这两个标签的节点是否存在。
四、MERGE
创建和匹配关系
4.1 MERGE 创建或匹配关系
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
MERGE (a)-[r:KNOWS]->(b)
RETURN a, b, r
MATCH
查找Alice
和Bob
节点。MERGE
尝试匹配KNOWS
关系,如果Alice
和Bob
之间没有KNOWS
关系,则创建关系。
4.2 MERGE 创建带有属性的关系
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
MERGE (a)-[r:KNOWS {since: 2020}]->(b)
RETURN a, b, r
MERGE
会检查KNOWS
关系是否存在,且since
属性为2020
。- 如果匹配不到,则创建新关系,并设置
since
属性。
4.3 MERGE 匹配无方向的关系
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
MERGE (a)-[r:FRIENDS]-(b)
RETURN a, b, r
- 匹配
Alice
和Bob
之间的无方向FRIENDS
关系。
4.4 MERGE 带有多个关系属性
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
MERGE (a)-[r:KNOWS {since: 2020, status: 'friends'}]->(b)
RETURN r
- 关系的属性
since
和status
需要完全匹配,才会返回现有的关系。
五、ON CREATE SET
和 ON MATCH SET
MERGE
允许使用 ON CREATE SET
和 ON MATCH SET
来指定不同情况下的属性更新规则。
5.1 ON CREATE SET
仅在创建时设置属性
MERGE (n:Person {name: 'Alice'})
ON CREATE SET n.age = 30, n.city = 'New York'
RETURN n
- 如果
Alice
节点不存在,MERGE
创建一个新的Person
节点,并设置age
和city
属性。 - 如果
Alice
已存在,则不会更改age
和city
的值。
5.2 ON MATCH SET
仅在匹配时更新属性
MERGE (n:Person {name: 'Alice'})
ON MATCH SET n.lastLogin = timestamp()
RETURN n
- 如果
Alice
节点已存在,则更新lastLogin
属性为当前时间戳。 - 如果
Alice
不存在,则不会执行ON MATCH SET
。
5.3 ON CREATE SET
和 ON MATCH SET
一起使用
MERGE (n:Person {name: 'Alice'})
ON CREATE SET n.age = 30, n.city = 'New York'
ON MATCH SET n.lastLogin = timestamp()
RETURN n
ON CREATE SET
和ON MATCH SET
可以同时使用,根据不同情况执行不同的属性更新逻辑。
5.4 更新关系属性
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
MERGE (a)-[r:KNOWS]->(b)
ON CREATE SET r.since = 2020
ON MATCH SET r.status = 'updated'
RETURN r
ON CREATE SET
为新创建的KNOWS
关系设置since
属性。ON MATCH SET
更新已存在的KNOWS
关系的status
属性。
六、MERGE
与 MATCH
、CREATE
的区别
6.1 MATCH
仅匹配,不创建
MATCH (n:Person {name: 'Alice'})
RETURN n
MATCH
只匹配现有的节点或关系,不会创建新的数据。- 如果没有匹配到数据,则返回空结果。
6.2 CREATE
始终创建新数据
CREATE (n:Person {name: 'Alice'})
RETURN n
CREATE
无论Alice
是否已存在,都会创建一个新的Person
节点。- 如果
Alice
已存在,可能会导致数据重复。
6.3 MERGE
结合了 MATCH
和 CREATE
的功能
MERGE (n:Person {name: 'Alice'})
RETURN n
MERGE
先尝试匹配数据,如果匹配不到,则创建新的数据。
6.4 区别总结
功能 | MATCH | CREATE | MERGE |
---|---|---|---|
匹配数据 | 仅匹配 | 不匹配 | 先匹配 |
创建数据 | 不创建 | 始终创建 | 匹配失败时创建 |
更新数据 | 不能更新 | 不能更新 | 可在匹配或创建时更新 |
七、MERGE
批量创建数据
7.1 使用 UNWIND
批量创建节点
UNWIND ['Alice', 'Bob', 'Charlie'] AS name
MERGE (n:Person {name: name})
RETURN n
UNWIND
将列表中的数据解包,并通过MERGE
匹配或创建节点。
7.2 使用 FOREACH
处理批量数据
FOREACH (name IN ['Alice', 'Bob', 'Charlie'] |
MERGE (n:Person {name: name})
)
FOREACH
循环处理数据,并使用MERGE
匹配或创建节点。
7.3 批量创建带关系的数据
UNWIND [
{person1: 'Alice', person2: 'Bob', since: 2020},
{person1: 'Alice', person2: 'Charlie', since: 2019}
] AS row
MATCH (p1:Person {name: row.person1}), (p2:Person {name: row.person2})
MERGE (p1)-[r:KNOWS]->(p2)
ON CREATE SET r.since = row.since
RETURN p1, p2, r
- 批量匹配
Person
节点,并为其创建KNOWS
关系,since
属性根据不同数据进行设置。
八、MERGE
的常见错误和注意事项
8.1 匹配多个属性时,属性需完全匹配
MERGE (n:Person {name: 'Alice', age: 30})
MERGE
需要name
和age
属性同时匹配才能匹配成功,否则创建新节点。
8.2 关系匹配仅匹配方向一致的关系
MATCH (a:Person {name: 'Alice'}), (b:Person {name: 'Bob'})
MERGE (a)-[r:KNOWS]->(b)
- 关系方向必须一致,否则
MERGE
不会匹配。
8.3 使用 MERGE
匹配多个属性时注意属性值类型
MERGE (n:Order {orderId: toInteger('123')})
- 属性的类型必须一致,否则
MERGE
无法正确匹配数据。
九、总结
MERGE
结合了MATCH
和CREATE
的功能,先尝试匹配数据,匹配失败时创建新的数据。MERGE
可以匹配或创建节点和关系,并结合ON CREATE SET
和ON MATCH SET
来更新数据。- 与
UNWIND
和FOREACH
结合使用时,MERGE
可实现批量数据的导入和处理。 MERGE
在处理数据时需要特别注意属性匹配的完整性、关系方向以及数据类型的一致性。
掌握 MERGE
语句的各种用法,可以在构建图数据模型时确保数据的唯一性,并避免重复数据的创建。