一、什么是 FOREACH
语句?
FOREACH
语句是 Cypher 中的一个循环控制语句,用于对列表中的每个元素执行特定的 Cypher 操作。
FOREACH
常用于批量创建、更新或删除节点、关系和属性。FOREACH
只能在MATCH
或UNWIND
之后使用,不能单独使用。
二、FOREACH
语法
FOREACH (variable IN list | operation)
语法说明:
variable
:循环变量,表示列表中的当前元素。list
:要遍历的列表。operation
:在每次迭代时执行的 Cypher 语句,可以是CREATE
、SET
、MERGE
、REMOVE
等操作。
三、FOREACH
的基本用法
3.1 批量创建节点
WITH ['Alice', 'Bob', 'Charlie'] AS names
FOREACH (name IN names |
CREATE (:Person {name: name})
)
- 遍历
names
列表中的每个元素,创建对应的Person
节点。
3.2 批量创建带有属性的节点
WITH [{name: 'Alice', age: 30}, {name: 'Bob', age: 25}] AS people
FOREACH (person IN people |
CREATE (:Person {name: person.name, age: person.age})
)
- 遍历
people
列表,为每个元素创建一个Person
节点,并设置name
和age
属性。
3.3 批量创建关系
MATCH (a:Person {name: 'Alice'})
WITH a, ['Bob', 'Charlie'] AS friends
FOREACH (friendName IN friends |
MERGE (b:Person {name: friendName})
CREATE (a)-[:KNOWS]->(b)
)
- 匹配
Alice
节点,为Bob
和Charlie
创建KNOWS
关系。
四、更新属性与标签
4.1 批量更新属性
MATCH (n:Person)
WITH n, ['active', 'verified'] AS statuses
FOREACH (status IN statuses |
SET n.status = status
)
SET
语句会在statuses
列表中依次更新n.status
属性,最终的值是列表中的最后一个元素verified
。
4.2 批量添加标签
MATCH (n:Person {name: 'Alice'})
WITH n, ['Employee', 'Manager'] AS labels
FOREACH (label IN labels |
SET n:label
)
- 使用
SET
为Alice
添加Employee
和Manager
标签。
4.3 批量删除属性
MATCH (n:Person {name: 'Alice'})
WITH n, ['age', 'city'] AS properties
FOREACH (prop IN properties |
REMOVE n[prop]
)
- 删除
Alice
节点中的age
和city
属性。
4.4 批量删除标签
MATCH (n:Person {name: 'Alice'})
WITH n, ['Employee', 'Manager'] AS labels
FOREACH (label IN labels |
REMOVE n:label
)
- 删除
Alice
节点的Employee
和Manager
标签。
五、使用 FOREACH
进行条件操作
5.1 基于条件批量创建关系
MATCH (a:Person {name: 'Alice'})
WITH a, ['Bob', 'Charlie'] AS friends
FOREACH (name IN friends |
MERGE (b:Person {name: name})
FOREACH (ignore IN CASE WHEN name <> 'Charlie' THEN [1] ELSE [] END |
CREATE (a)-[:KNOWS]->(b)
)
)
- 仅为
Alice
创建KNOWS
关系,但排除Charlie
。
5.2 根据条件批量更新节点
MATCH (n:Person)
WITH n, [n.age, n.city] AS attributes
FOREACH (attr IN attributes |
FOREACH (ignore IN CASE WHEN attr IS NOT NULL THEN [1] ELSE [] END |
SET n.updated = true
)
)
- 如果
age
或city
属性不为空,则设置updated
为true
。
六、批量删除数据
6.1 批量删除关系
MATCH (a:Person {name: 'Alice'})-[r:KNOWS]->(b:Person)
WITH r
FOREACH (rel IN [r] |
DELETE rel
)
- 批量删除
Alice
的所有KNOWS
关系。
6.2 批量删除节点
MATCH (n:Person)
WITH n
FOREACH (ignore IN [n] |
DETACH DELETE n
)
- 删除
Person
节点及其所有关系。
七、FOREACH
与 UNWIND
的区别
7.1 FOREACH
:用于批量操作
- 只能在
MATCH
、WITH
或UNWIND
之后使用。 - 适合执行更新、删除等具有副作用的语句。
7.2 UNWIND
:将列表拆分为单独的行
UNWIND
会将列表展开为多个行,并可与MATCH
、CREATE
、MERGE
等语句配合使用。- 适合创建新数据或匹配现有数据。
示例比较:
WITH ['Alice', 'Bob', 'Charlie'] AS names
FOREACH (name IN names |
CREATE (:Person {name: name})
)
等效于:
UNWIND ['Alice', 'Bob', 'Charlie'] AS name
CREATE (:Person {name: name})
八、常见错误与注意事项
8.1 FOREACH
不能单独使用
FOREACH (name IN ['Alice', 'Bob'] |
CREATE (:Person {name: name})
)
- 直接使用
FOREACH
会报错,必须在WITH
、MATCH
或UNWIND
之后使用。
8.2 FOREACH
只能包含 DML 操作
FOREACH
只能包含数据修改操作,如CREATE
、SET
、MERGE
、REMOVE
、DELETE
等。- 不能使用
RETURN
、WITH
或MATCH
等语句。
8.3 列表不能为空
WITH [] AS names
FOREACH (name IN names |
CREATE (:Person {name: name})
)
- 如果
names
为空,FOREACH
不会执行任何操作,但不会报错。
九、FOREACH
的高级用法
9.1 批量创建不同类型的关系
MATCH (a:Person {name: 'Alice'})
WITH a, [{name: 'Bob', rel: 'KNOWS'}, {name: 'Charlie', rel: 'FRIENDS_WITH'}] AS connections
FOREACH (conn IN connections |
MERGE (b:Person {name: conn.name})
CREATE (a)-[:`+ conn.rel +`]->(b)
)
- 根据不同的
rel
属性创建不同类型的关系。
9.2 使用 CASE
实现条件操作
MATCH (n:Person)
WITH n, [n.age, n.city] AS attributes
FOREACH (attr IN attributes |
FOREACH (ignore IN CASE WHEN attr IS NOT NULL THEN [1] ELSE [] END |
SET n.updated = true
)
)
- 如果
age
或city
不为空,则更新updated
属性。
9.3 删除特定条件下的关系
MATCH (a:Person)-[r:KNOWS]->(b:Person)
WITH r
FOREACH (rel IN CASE WHEN r.since < 2020 THEN [r] ELSE [] END |
DELETE rel
)
- 仅删除
since < 2020
的KNOWS
关系。
十、总结
FOREACH
是 Cypher 中的批量操作语句,适用于对列表中的每个元素执行批量CREATE
、SET
、MERGE
、REMOVE
和DELETE
等操作。FOREACH
语句只能在MATCH
、WITH
或UNWIND
之后使用,且不能包含RETURN
语句。FOREACH
主要用于批量数据处理、更新或删除属性和标签、创建或删除关系等操作。- 在大规模数据操作时,
FOREACH
提供了一种高效的方式来完成数据的批量修改,提升图数据库的维护和分析能力。