Neo4j 3.0 提供一个新的功能“存储过程”,该功能并不是Neo4j-Server的扩展,而是可以直接运行的。
在写这篇文章的时候,只能通过预备好的语句去执行
1 | CALL package .procedure(params)
|
但是接下来他会被完全集成到Cypher语句当中。这样我梦就可以通过CALL这个语句或者将它转换成方法表达式(这只是个人喜好)。 现在,“存储过程”只能使用Java(或者其他JVM语言)。你可能获说,“WTF 。。。java”, 其实java也没有那么一无是处。
一开始,在建立,编码,编译一个存储过程并不会花费太多的精力,只需要下载Neo4j 3.0, 3.0.0-M04 milestone或者最新的版本,同时JDK,Gradle或者Maven也需要安装。
我们可以直接使用Jake Hansson写好的一个模板neo4j-examples,这样可以更快的开始我们的第一个练习。 我们举一个简单的例子(GitHub Repository),你需要说明一下org.neo4j:neo4j:3.0.0[-M04]可以得到的取值范围, 来获得必需的注释,然后Neo4j API才能讨论数据库。 1 2 3 4 5 6 | <dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>${neo4j.version}</version>
<scope>provided</scope>
</dependency>
|
Gradle 如下 1 2 3 4 5 6 7 8 9 | project.ext {
neo4j_version = ""
}
dependencies {
compile group: "org.neo4j" , name: "neo4j" , version:project.neo4j_version
testCompile group: "org.neo4j" , name: "neo4j-kernel" , version:project.neo4j_version, classifier: "tests"
testCompile group: "org.neo4j" , name: "neo4j-io" , version:project.neo4j_version, classifier: "tests"
testCompile group: "junit" , name: "junit" , version: 4.12
}
|
如果你想写一些其他的程序,你只需要重新建立一个文件夹和新的类。
需要注意的是包和方法的名字变成了存储过程的名字(并不是类的名字)。 在我们的例子中,我们将写一个简单的存储过程来计算某个标签的最大和最小度数。 通过@Context标注可以讲Neo4j的 GraphDatabaseService 实例注入到你的类中。因为存储过程是无状态的,所以声明非注入非静态的字段是不允许的。 在我们的例子中,存储过程将命名为stats.degree,以CALL stats.degree('User')的形式进行调用。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | package stats;
public class GraphStatistics {
@Context private GraphDatabaseService db;
public static class Degree {
public String label;
public long count, max, min = Long.MAX_VALUE;
private void add( long degree) {
if (degree < min) min = degree;
if (degree > max) max = degree;
count ++;
}
}
@Procedure
public Stream<Degree> degree(String label) {
Degree degree = new Degree(label);
try (ResourceIterator it = db.findNodes(Label.label(label))) {
while (it.hasNext()) {
d.add(it.next().getDegree());
}
}
return Stream.of(degree);
}
}
|
如果你要快速的测试这个存储过程,又不想启动一个进程内服务端再连接上(比如,存储过程模板中演示的通过新的二进制的通信协议),你可以使用Neo4j测试工具集提供的Java API。
现在,我们可以写一个单元测试来测试下我们刚写的酷炫的存储过程。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package stats;
class GraphStatisticsTest {
@Test public void testDegree() {
db.execute( "CREATE (alice:User)-[:KNOWS]->(bob:User),(alice)-[:KNOWS]->(charlie:User),(dan:User)" ).close();
Result res = db.execute( "CALL stats.degree('User')" );
assertTrue(res.hasNext());
Map<String,Object> row = res.next();
assertEquals( "User" , row.get( "label" ));
assertEquals( 0 , row.get( "min" ));
assertEquals( 2 , row.get( "max" ));
assertEquals( 4 , row.get( "count" ));
assertFalse(res.hasNext());
}
}
|
当然,你可以使用存储过程来生成更多的存储过程,比如其他原生支持JVM的语言,比如 JavaScript via Nashorn, Clojure,Groovy, Scala, Frege (Haskell), (J)Ruby or (J/P)ython。 我用JavaScript写了一个生成和运行存储过程的程序。 你还可以用存储过程做很多其他很酷的事情,比如下面列的资源。 如果你有写一些自己的存储过程的想法,请联系我们。
其他资源
|