6.1 APOC 实用手册:Cypher 的外挂工具箱 本节摘要:APOC(Awesome Procedures on Cypher)用几百个内置过程与函数补齐 Cypher 不方便做的事:动态构造查询、批量参数处理、JSON 往返、条件执行、跨库遍历。本节讲清"过程 vs 函数"的机制差异,按类别给出工具地图,深挖三个最高频场景,并交代依赖管理与版本匹配的工程纪律。 第 5 章见过 过程的调用方式,本节的 同族而不同职:GDS 管算法,APOC 管日常工具。官方称其为 Cypher 的"外挂工具箱",实至名归——多数"Cypher 写不出来"的困扰,答案都藏在 APOC 里。 一、机制:过程与函数的调用差异 先分清两种形态。过程用 CALL 调用、可 YIELD 多列;
本节摘要:APOC(Awesome Procedures on Cypher)用几百个内置过程与函数补齐 Cypher 不方便做的事:动态构造查询、批量参数处理、JSON 往返、条件执行、跨库遍历。本节讲清"过程 vs 函数"的机制差异,按类别给出工具地图,深挖三个最高频场景,并交代依赖管理与版本匹配的工程纪律。
第 5 章见过 gds.* 过程的调用方式,本节的 apoc.* 同族而不同职:GDS 管算法,APOC 管日常工具。官方称其为 Cypher 的"外挂工具箱",实至名归——多数"Cypher 写不出来"的困扰,答案都藏在 APOC 里。
先分清两种形态。过程用 CALL 调用、可 YIELD 多列;函数嵌在表达式里、返回单值:
// 过程:CALL + YIELD,独立成一行语句 CALL apoc.util.sleep(100) YIELD value RETURN value // 函数:嵌在表达式里,像内置函数一样用 RETURN apoc.text.join(['Neo', '4j'], '') AS word
word ---- Neo4j
大多数 APOC 能力不需要装插件,但涉及文件系统与跨库连接的过程要在配置里显式开启——这个开关的存在本身就是一种安全设计。
| 想做什么 | 首选过程/函数 | 一句话说明 |
|---|---|---|
| 动态设置/查询任意属性 | apoc.create.setProperty、apoc.map.* |
属性名在运行时才确定 |
| 批量处理大列表 | apoc.periodic.iterate |
分批自动提交,防大事务 |
| JSON 与 Cypher 互转 | apoc.convert.toJson、apoc.load.json |
接口数据直接进图 |
| 条件分支执行 | apoc.case、apoc.do.when |
在一条查询里 if-else |
| 图结构导出 | apoc.export.json 等 |
把子图序列化带走 |
| 文本与日期工具 | apoc.text.*、apoc.date.* |
格式化、解析、正则 |
| 生成测试数据 | apoc.generate.* |
随机图快速造沙盘 |
不用背全表。记住检索方法:CALL apoc.help('关键词') 现场查文档,比任何清单都及时。
属性名来自业务字段(如用户自定义字段),静态 Cypher 写不出 $dynamicName——APOC 补位:
// 属性名运行时决定:$field 是 "age" 或任意列名 MERGE (p:Person {email: $email}) WITH p, $field AS fName, $value AS fValue CALL apoc.create.setProperty(p, fName, fValue) YIELD node RETURN node.email
输入 field = "nickname", value = "阿梦" → 节点获得 nickname 属性,Cypher 原生语法做不到
批量参数化管道则用 apoc.create.addLabels 与 UNWIND 组合,动态加标签:
UNWIND $rows AS row MATCH (p:Person {email: row.email}) CALL apoc.create.addLabels(p, [row.segment]) YIELD node RETURN count(node) AS 打标人数
rows: [{email: 'a@x.com', segment: 'VIP'}, ...] → 每人按运营分段挂标签,标签名由数据驱动
3.2 节的纪律"事务要短",在"全库回填一个属性"这类任务上如何落地?一条查询更新一千万节点必然超长——apoc.periodic.iterate 把它自动切批:
// 第一参数:流(取数据);第二参数:批内动作;第三参数:批大小与并行度 CALL apoc.periodic.iterate( 'MATCH (p:Person) RETURN p', 'SET p.fullText = p.name + " " + coalesce(p.title, "")', {batchSize: 10000, parallel: true} ) YIELD batches, total, errorMessages RETURN batches, total, errorMessages
batches: 137 -- 自动切了 137 批,每批独立事务 total: 1,362,000 errorMessages: [] -- 有错也会逐批报告,不会全盘回滚

Cypher 没有原生 if-else 语句,CASE 只能算值不能"选择性执行写入"。APOC 补上这个洞:
// 库存低于阈值走补货,否则走标记 MATCH (p:Product {sku: $sku}) CALL apoc.case( [p.stock < 10, "SET p.reorder = true", p.stock < 50, "SET p.lowStock = true"], elseQuery = "SET p.healthy = true" ) YIELD value RETURN p.sku, p.stock
💡 用 APOC 的前提是"确实需要",而不是"它会":能用原生 Cypher 表达的逻辑优先原生——APOC 过程多一层调用开销,且让查询对插件版本产生依赖。
APOC 以附加包形式发布,版本必须与 Neo4j 主版本严格匹配——版本错配是升级后"过程突然找不到"的头号原因。团队纪律三条:生产库统一版本并入库管管理清单;禁用不需要的文件类过程;把用到的 APOC 调用集中封装(沿用 4.3 的仓库层原则),升级时才好回归。
apoc.help);periodic.iterate:切批、并行、逐批报告;工程师的工具箱齐了。下一节换角色:业务人员怎么看图——Bloom。