存储过程 #

一、存储过程概述 #

1.1 什么是存储过程 #

存储过程是预编译的可重用代码块,可以执行复杂操作。

text
存储过程特点:
├── 封装复杂逻辑
├── 提高代码复用
├── 支持参数传递
├── 可返回多个结果
└── 可用Java编写

1.2 内置存储过程 #

Neo4j提供多种内置存储过程:

类别 示例
数据库管理 db.labels, db.relationshipTypes
索引管理 db.indexes, db.awaitIndex
事务管理 dbms.listTransactions
用户管理 dbms.security.listUsers

二、CALL语句 #

2.1 基本语法 #

cypher
CALL procedure.name()

2.2 带参数调用 #

cypher
CALL procedure.name(param1, param2)

2.3 使用YIELD返回结果 #

cypher
CALL db.labels() YIELD label
RETURN label

2.4 过滤结果 #

cypher
CALL db.indexes() YIELD name, state
WHERE state = 'ONLINE'
RETURN name

2.5 与其他子句组合 #

cypher
CALL db.labels() YIELD label
MATCH (n)
WHERE label IN labels(n)
RETURN label, count(n) AS count
ORDER BY count DESC

三、内置存储过程 #

3.1 数据库信息 #

cypher
CALL db.info()

3.2 标签列表 #

cypher
CALL db.labels()

3.3 关系类型列表 #

cypher
CALL db.relationshipTypes()

3.4 属性键列表 #

cypher
CALL db.propertyKeys()

3.5 索引列表 #

cypher
CALL db.indexes()

3.6 约束列表 #

cypher
CALL db.constraints()

3.7 统计信息 #

cypher
CALL db.stats.retrieve('GRAPH COUNTS')

四、APOC库 #

4.1 APOC概述 #

APOC (Awesome Procedures on Cypher) 是Neo4j最流行的扩展库。

text
APOC功能:
├── 数据转换
├── 图算法
├── 文本处理
├── 日期时间
├── 数学运算
├── 集合操作
├── 虚拟关系
└── 批处理

4.2 安装APOC #

  1. 下载APOC jar文件
  2. 放入plugins目录
  3. 重启Neo4j

或在neo4j.conf中配置:

properties
dbms.security.procedures.unrestricted=apoc.*
dbms.security.procedures.allowlist=apoc.*

4.3 查看APOC过程 #

cypher
CALL apoc.help('all')

4.4 常用APOC函数 #

文本处理 #

cypher
RETURN apoc.text.replace('Hello World', 'World', 'Neo4j')
RETURN apoc.text.capitalize('hello')
RETURN apoc.text.capitalizeAll('hello world')

集合操作 #

cypher
RETURN apoc.coll.union([1, 2], [2, 3])
RETURN apoc.coll.intersection([1, 2, 3], [2, 3, 4])
RETURN apoc.coll.difference([1, 2, 3], [2, 3, 4])

日期时间 #

cypher
RETURN apoc.date.currentTimestamp()
RETURN apoc.temporal.format(date(), 'yyyy-MM-dd')

JSON处理 #

cypher
RETURN apoc.convert.toJson({name: 'Tom', age: 30})
RETURN apoc.convert.fromJsonMap('{"name":"Tom","age":30}')

4.5 APOC图操作 #

批量创建 #

cypher
CALL apoc.create.nodes(['Person'], [
    {name: 'Tom'},
    {name: 'Jerry'}
])

批量处理 #

cypher
CALL apoc.periodic.iterate(
    'MATCH (p:Person) RETURN p',
    'SET p.processed = true',
    {batchSize: 1000}
)

路径展开 #

cypher
MATCH (start:Person {name: 'Tom'})
CALL apoc.path.expand(start, 'KNOWS>', null, 1, 3) YIELD path
RETURN path

4.6 APOC虚拟关系 #

cypher
MATCH (a:Person)-[:KNOWS]->(b:Person)
WITH a, count(b) AS friendCount
CALL apoc.create.vRelationship(a, 'FRIEND_COUNT', {count: friendCount}, null) YIELD rel
RETURN a, rel

五、自定义存储过程 #

5.1 创建Java存储过程 #

java
package com.example;

import org.neo4j.procedure.*;
import org.neo4j.graphdb.*;

public class CustomProcedures {
    
    @Context
    public GraphDatabaseService db;
    
    @Procedure(name = "com.example.hello", mode = Mode.READ)
    @Description("Returns a hello message")
    public Stream<HelloResult> hello(@Name("name") String name) {
        return Stream.of(new HelloResult("Hello, " + name + "!"));
    }
    
    public static class HelloResult {
        public String message;
        
        public HelloResult(String message) {
            this.message = message;
        }
    }
}

5.2 注册存储过程 #

  1. 编译Java代码为JAR文件
  2. 放入plugins目录
  3. 重启Neo4j

5.3 调用自定义过程 #

cypher
CALL com.example.hello('Tom') YIELD message
RETURN message

六、存储过程最佳实践 #

6.1 性能优化 #

text
建议:
├── 使用索引加速查询
├── 限制返回结果数量
├── 使用分批处理大数据量
├── 避免复杂计算
└── 合理使用缓存

6.2 安全考虑 #

text
安全建议:
├── 限制存储过程权限
├── 验证输入参数
├── 避免SQL注入
├── 使用参数化查询
└── 记录操作日志

6.3 错误处理 #

cypher
CALL apoc.do.when(
    EXISTS((:Person {name: 'Tom'})),
    'RETURN "Person exists" AS result',
    'CREATE (p:Person {name: "Tom"}) RETURN "Person created" AS result',
    {}
) YIELD value
RETURN value.result

七、实际应用示例 #

7.1 批量数据导入 #

cypher
CALL apoc.periodic.iterate(
    'LOAD CSV WITH HEADERS FROM "file:///data.csv" AS row RETURN row',
    'CREATE (p:Person {id: row.id, name: row.name})',
    {batchSize: 1000, parallel: true}
)

7.2 数据清理 #

cypher
CALL apoc.periodic.iterate(
    'MATCH (p:Person) WHERE p.status = "deleted" RETURN p',
    'DETACH DELETE p',
    {batchSize: 1000}
)

7.3 图遍历 #

cypher
MATCH (start:Person {name: 'Tom'})
CALL apoc.path.expandConfig(start, {
    relationshipFilter: 'KNOWS>',
    minLevel: 1,
    maxLevel: 3,
    uniqueness: 'NODE_GLOBAL'
}) YIELD path
RETURN path

7.4 数据转换 #

cypher
MATCH (p:Person)
WITH p, apoc.text.capitalize(p.name) AS capitalizedName
SET p.capitalizedName = capitalizedName

八、总结 #

存储过程要点:

操作 语法 说明
调用过程 CALL procedure() 调用存储过程
返回结果 YIELD column 获取返回列
APOC函数 apoc.function() APOC库函数
批量处理 apoc.periodic.iterate() 批量迭代处理

最佳实践:

  1. 合理使用内置过程
  2. 安装APOC扩展功能
  3. 使用批量处理提高性能
  4. 注意安全权限控制
  5. 正确处理错误

下一步,让我们学习用户权限管理!

最后更新:2026-03-27