Neo4j-03.Cypher增删改查

掌握 Cypher 的增删改查是 Neo4j 日常开发的基线能力。本文在 Neo4j-01 入门示例之上,系统梳理 CRUD(create, read, update, delete,增删改查)、幂等写入、约束与事务——覆盖应用开发与数据同步的常见写法。


一、读(Read):MATCH 与 RETURN

1.1 基础匹配

1
2
3
4
5
6
7
8
9
// 按标签 + 属性
MATCH (p:Person {name: 'Alice'})
RETURN p;

// 多标签
MATCH (e:Protein:Enzyme)
WHERE e.organism = 'Homo sapiens'
RETURN e.uniprot, e.name
LIMIT 20;

1.2 关系模式

1
2
3
4
5
6
7
8
9
10
11
12
// 指定方向与类型
MATCH (a:Person)-[:KNOWS]->(b:Person)
RETURN a.name, b.name;

// 任意方向、任意类型(慎用,易全图扫描)
MATCH (a)-[r]-(b)
RETURN type(r), count(*)
LIMIT 10;

// 变长路径:1~3 跳 KNOWS
MATCH (a:Person {name: 'Alice'})-[:KNOWS*1..3]->(d)
RETURN DISTINCT d.name;

1.3 可选匹配与聚合

1
2
3
4
5
6
7
8
9
// OPTIONAL MATCH:左连接语义,无匹配时 NULL
MATCH (p:Person)
OPTIONAL MATCH (p)-[:WORKS_AT]->(c:Company)
RETURN p.name, c.name AS company;

// 计数
MATCH (p:Person)-[:KNOWS]->(f)
RETURN p.name, count(f) AS friend_count
ORDER BY friend_count DESC;

1.4 排序、分页、去重

1
2
3
4
MATCH (n:Paper)
RETURN DISTINCT n.journal
ORDER BY n.journal
SKIP 100 LIMIT 50;

二、增(Create)

2.1 CREATE:总是新建

1
2
CREATE (p:Person {id: randomUUID(), name: 'Carol', created: datetime()})
RETURN p;
1
2
3
// 一次创建路径
CREATE (a:Person {name: 'Dave'})-[:KNOWS {since: date('2024-06-01')}]->(b:Person {name: 'Eve'})
RETURN a, b;

注意:重复执行会产生重复节点,除非有唯一约束 + MERGE。

2.2 MERGE:幂等 upsert

1
2
3
4
MERGE (p:Person {email: 'alice@example.com'})
ON CREATE SET p.created = timestamp(), p.name = 'Alice'
ON MATCH SET p.updated = timestamp()
RETURN p;
1
2
3
4
5
// MERGE 整条模式(节点 + 关系)
MERGE (a:Person {name: 'Alice'})
MERGE (b:Person {name: 'Bob'})
MERGE (a)-[r:KNOWS]->(b)
ON CREATE SET r.since = 2020;
语句 语义
CREATE 无条件新建
MERGE 按模式匹配,不存在则创建

三、改(Update):SET / REMOVE

3.1 更新属性

1
2
3
MATCH (p:Person {name: 'Alice'})
SET p.age = 31, p.title = 'Engineer'
RETURN p;

3.2 标签与属性删除

1
2
3
4
5
MATCH (p:Person {name: 'Alice'})
SET p:Employee // 增加标签
REMOVE p:Intern // 移除标签
REMOVE p.tempField // 删除属性
RETURN labels(p), properties(p);

3.3 关系属性更新

1
2
MATCH (a:Person {name: 'Alice'})-[r:KNOWS]->(b:Person {name: 'Bob'})
SET r.strength = 0.85, r.lastContact = date();

3.4 条件更新(CASE)

1
2
3
4
5
6
MATCH (p:Person)
SET p.tier = CASE
WHEN p.score >= 90 THEN 'gold'
WHEN p.score >= 70 THEN 'silver'
ELSE 'bronze'
END;

四、删(Delete)

4.1 删关系

1
2
MATCH (a:Person {name: 'Alice'})-[r:KNOWS]->(b:Person {name: 'Bob'})
DELETE r;

4.2 删节点

1
2
3
4
5
6
7
// 无关系的节点
MATCH (p:Person {name: 'Temp'})
DELETE p;

// 有关系的节点:必须 DETACH DELETE
MATCH (p:Person {name: 'Alice'})
DETACH DELETE p;

4.3 批量删除(生产谨慎)

1
2
3
4
5
6
// 分批删,避免大事务 OOM
CALL {
MATCH (n:Stale)
WITH n LIMIT 10000
DETACH DELETE n
} IN TRANSACTIONS OF 10000 ROWS;

Neo4j 5+ 支持 CALL { ... } IN TRANSACTIONS 自动分批提交。


五、约束与索引(数据质量 + 性能)

Neo4j Browsercypher-shell 中执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 唯一约束(自动建索引)
CREATE CONSTRAINT person_email IF NOT EXISTS
FOR (p:Person) REQUIRE p.email IS UNIQUE;

// 存在性约束
CREATE CONSTRAINT paper_doi IF NOT EXISTS
FOR (p:Paper) REQUIRE p.doi IS NOT NULL;

// 普通属性索引
CREATE INDEX person_name IF NOT EXISTS
FOR (p:Person) ON (p.name);

// 复合索引(Neo4j 5.20+)
CREATE INDEX person_name_age IF NOT EXISTS
FOR (p:Person) ON (p.name, p.age);

// 关系属性索引
CREATE INDEX knows_since IF NOT EXISTS
FOR ()-[r:KNOWS]-() ON (r.since);
类型 作用
UNIQUE 保证业务键唯一;MERGE 锚点
NOT NULL 必填字段
INDEX 加速 WHERE 过滤

查看已有约束:

1
2
SHOW CONSTRAINTS;
SHOW INDEXES;

六、参数化查询(防注入 + 计划缓存)

6.1 Browser / cypher-shell

1
2
:param name => 'Alice';
MATCH (p:Person {name: $name}) RETURN p;

6.2 Python 驱动

1
2
3
4
5
driver.execute_query(
"MATCH (p:Person {name: $name}) RETURN p",
name="Alice",
database_="neo4j",
)

永远不要拼接字符串构造 Cypher。


七、事务语义

Neo4j 支持 ACID 事务(单库内):

层级 说明
自动事务 每条 Cypher 默认一条事务
显式事务 驱动 session.execute_write() 内多条语句同一事务
隔离 默认可重复读;写冲突时后者失败

Python 显式事务示例:

1
2
3
4
5
6
7
8
9
10
11
12
def create_friendship(tx, name_a, name_b):
tx.run(
"""
MERGE (a:Person {name: $a})
MERGE (b:Person {name: $b})
MERGE (a)-[:KNOWS]->(b)
""",
a=name_a, b=name_b,
)

with driver.session() as session:
session.execute_write(create_friendship, "Alice", "Bob")

八、常用 CRUD 模式速查

意图 Cypher 模式
按主键 upsert 节点 MERGE (n:Label {id: $id}) SET n += $props
upsert 边 MERGE (a)-[r:TYPE]->(b) SET r += $props
软删除 SET n.deleted = true, n.deletedAt = timestamp()
硬删子图 MATCH (n:Root {id: $id}) DETACH DELETE n
只删某类型关系 MATCH ()-[r:OLD_TYPE]->() DELETE r
属性批量刷新 MATCH (n:Label) SET n.version = $v

九、与 SQL 对照(帮助 SQL 背景读者)

SQL Cypher
INSERT CREATE / MERGE
SELECT ... JOIN MATCH ... RETURN
UPDATE ... SET MATCH ... SET
DELETE DELETE / DETACH DELETE
WHERE WHERE(在 MATCH 后)
GROUP BY RETURN ... count()
外键约束 CREATE CONSTRAINT ... UNIQUE

十、小结

  • MATCH + RETURN;多跳用 *min..max;左连接用 OPTIONAL MATCH
  • 区分 CREATE(必新建)与 MERGE(幂等);生产同步几乎总是 MERGE。
  • SET / REMOVE关系用 DELETE,删节点用 DETACH DELETE
  • 唯一约束是 MERGE 正确性的前提;大批量删除用 IN TRANSACTIONS 分批。
下一篇 内容
Neo4j-04.数据导入与对接工具 LOAD CSV、bulk import、驱动
Neo4j-05.查询进阶与性能调优 EXPLAIN、路径优化
-------------本文结束感谢您的阅读-------------