第 10 章 扩展 Neo4j 服务器
目录
10.1. 服务器插件
10.2. 非托管扩展
Neo4j服务器可以通过插件或者非托管扩展来增强。为了获取更多关于服务器的信息,请参考:第 17 章 Neo4j服务器。
10.1. 服务器插件
内容提示
- 服务器的功能可以通过增加插件的方式来增强。
- 插件是用户自己编码完成的,以便增强数据库,节点以及属性的功能。
- Neo4j服务器在与客户端通过HTTP方式进行交互时使用这些自定义插件。
插件提供了一种增加Neo4j Rest API新功能的很好的方式,而不需要去从新发明你自己的API。作为在服务端运行的脚本,插件可以用于接受和维护节点,关系,路径,属性以及指数。
提示 | ||
如果你想完全控制你的API,你需要多花心思,并理解这样做的风险,而Neo4j服务端也可以通过JAX-RS提供非托管的扩展。 |
涉及到的类在jar包org.neo4j:server-api中,看看下载页面的链接地址,介绍了如何引入。对于一个Maven工程,新增 服务端 API依赖到你的工程中,你可以修改 pom.xml像下面这样:
1 2 3 4 5 | <dependency> <groupId>org.neo4j</groupId> <artifactId>server-api</artifactId> <version>${neo4j-version}</version> </dependency> |
_ ${neo4j-version} 是一个版本号。_
为了创建插件,你的代码必须继承类: ServerPlugin。你的插件必须做到下面几点:
- 确定插件可以产生一个(一组)节点,关系或者路径,或者任何Java原生类型以及字符串
- 可以指定参数,
- 可以指定一个扩展点
- 包括应用逻辑。
- 确定在 @PluginTarget和 @Source参数中可以发现类型。
下面是一个插件的范例,参数是数据库(也可以是节点或者关系):
获取所有节点和关系的插件.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @Description( "An extension to the Neo4j Server for getting all nodes or relationships") publicclassGetAll extendsServerPlugin { @Name( "get_all_nodes") @Description( "Get all nodes from the Neo4j graph database") @PluginTarget( GraphDatabaseService.class) publicIterable<Node> getAllNodes( @SourceGraphDatabaseService graphDb ) { returnGlobalGraphOperations.at( graphDb ).getAllNodes(); } @Description( "Get all relationships from the Neo4j graph database") @PluginTarget( GraphDatabaseService.class) publicIterable<Relationship> getAllRelationships( @SourceGraphDatabaseService graphDb ) { returnGlobalGraphOperations.at( graphDb ).getAllRelationships(); } } |
完整源代码下载地址: GetAll.java
找到两点之间最短距离的插件.
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 | publicclassShortestPath extendsServerPlugin { @Description( "Find the shortest path between two nodes.") @PluginTarget( Node.class) publicIterable<Path> shortestPath( @SourceNode source, @Description( "The node to find the shortest path to.") @Parameter( name = "target") Node target, @Description( "The relationship types to follow when searching for the shortest path(s). "+ "Order is insignificant, if omitted all types are followed.") @Parameter( name = "types", optional = true) String[] types, @Description( "The maximum path length to search for, default value (if omitted) is 4.") @Parameter( name = "depth", optional = true) Integer depth ) { Expander expander; if( types == null) { expander = Traversal.expanderForAllTypes(); } else { expander = Traversal.emptyExpander(); for( inti = 0; i < types.length; i++ ) { expander = expander.add( DynamicRelationshipType.withName( types[i] ) ); } } PathFinder<Path> shortestPath = GraphAlgoFactory.shortestPath( expander, depth == null? 4: depth.intValue() ); returnshortestPath.findAllPaths( source, target ); } } |
完整源代码下载地址: ShortestPath.java
为了部署代码,可以简单的编译成.jar 文件并把他放到服务器的classpath下面(按照惯例,插件目录在Neo4j 服务端的主目录下面)。
提示 | |
确保通过Maven或者 `jar -cvf myext.jar *`编译时,目录列表被保留在jar文件中,确定jar目录代替指定的单个文件。 |
'.jar' 文件必须包括 'META-INF/services/org.neo4j.server.plugins.ServerPlugin' 。
这是一个范例,有多个入口,每一个都在下面独立的一行:
1 2 3 | org.neo4j.examples.server.plugins.GetAll org.neo4j.examples.server.plugins.DepthTwo org.neo4j.examples.server.plugins.ShortestPath |
上面的代码让一个扩展在接收来自Neo4j 服务端的服务时,总是在数据库中可见(通过 @PluginTarget注解)。简单的改变 @PluginTarget参数成 Node.class或者 Relationship.class,就可以让我们轻松的切换到我们希望的其他数据模型。通过插件提供的功能性扩展会自动生效的。比如,客户端与服务端交互时,可以通过上面的插件提供的扩展,更早的检查他们接收到的反馈。比如在默认数据库URI上发送一个 GET请求:
1 | curl -vhttp://localhost:7474/db/data/ |
对于 GET请求的反馈是默认情况下会是一个JSON数据,里面有一属性”extensions“,列出了所有可以使用的插件。在下面例子中,我们只有 GetAll插件注册到了服务端,所以只有他的扩展功能是可以使用的。扩展名如果没有通过 @Name指定的话会被自动分配,基于方法名。
1 2 3 4 5 6 7 8 9 10 11 12 13 | { "extensions-info": "http://localhost:7474/db/data/ext", "node": "http://localhost:7474/db/data/node", "node_index": "http://localhost:7474/db/data/index/node", "relationship_index": "http://localhost:7474/db/data/index/relationship", "reference_node": "http://localhost:7474/db/data/node/0", "extensions_info": "http://localhost:7474/db/data/ext", "extensions": { "GetAll": { "get_all_nodes": "http://localhost:7474/db/data/ext/GetAll/graphdb/get_all_nodes", "get_all_relationships": "http://localhost:7474/db/data/ext/GetAll/graphdb/getAllRelationships" } } |
在两个扩展URI上面做 GET请求获取meta信息:
1 | curl http://localhost:7474/db/data/ext/GetAll/graphdb/get_all_nodes |
1 2 3 4 5 6 | { "extends": "graphdb", "description": "Get all nodes from the Neo4j graph database", "name": "get_all_nodes", "parameters": [ ] } |
为了使用它,需要 POST到这个地址,并带上指定的参数和JSON数据。比如我们调用 shortest path扩展(URI通过发送 GET请求到 http://localhost:7474/db/data/node/123获取 ):
1 2 3 | curl -X POST http://localhost:7474/db/data/ext/GetAll/node/123/shortestPath\ -H "Content-Type: application/json"\ -d '{"target":"http://localhost:7474/db/data/node/456&depth=5"}' |
如果一切顺利,将返回状态码: 200和一些0或者更多的数据。如果没有任何返回,将返回状态码: 204。如果扩展出现异常,将返回状态码: 500以及异常错误信息。
那些需要进行写操作的扩展必须管理他们自己的事务。事务不能自动被管理的。
通过这个模型,任何插件都会很自然的适应任何Neo4j支持的超媒体 — 这意味着客户端在像节点,关系和路径这些抽象的一个简单的升级路径上占有优势,因为服务端已经被插件增强了(老客户端不会)。
10.2. 非托管扩展
内容提示
- 危险:Men at Work! 非托管扩展是部署随意的JAX-RS代码进Neo4j服务器的一种方式。
- 非托管扩展更准确的说是:非托管。 如果你把没有经过完整单元测试的代码放入了服务器,有很高的几率会降低服务器性能,所以请小心使用。
一些工程希望更加友好的管控他们的服务端代码。为此,我们将介绍一些非托管API。
警告 | |
这是一把双刃剑,它允许用户随意部署 JAX-RS类到服务端,因此你要小心使用。特别是你应该明白,他会轻易的就占用服务端的大量的堆空间,降低你可能不关心的服务端的性能。 |
当然,如果你了解这些,你可以简单的通过一个 @Context注解加入到你的代码,然后把你的JAX-RS类编译成JAX-RS jar文件,加载进Neo4j服务端。然后增加你的类到运行时路径(classpath)中(只需要把他放到Neo4j服务端的目录中)。你可以使用通过 org.neo4j.server.logging.Logger使用日志功能,获取Neo4j服务端的主机环境信息。
在你的代码中,你可以通过 @Context访问 GraphDatabaseService:
1 2 3 4 | publicMyCoolService( @ContextGraphDatabaseService database ) { // Have fun here, but be safe! } |
记住,非托管API是一种非常高效的工具。他是通过部署代码来影响服务器的最容易的方式,因此我们首先应该想到的是你不能优先使用非托管扩展。然而,大量的上下文参数可以提供给你,像数据库引用。
为了指定你的扩展的挂载点,完整的类应该像这样:
非托管扩展范例.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @Path( "/helloworld") publicclassHelloWorldResource { privatefinalGraphDatabaseService database; publicHelloWorldResource( @ContextGraphDatabaseService database ) { this.database = database; } @GET @Produces( MediaType.TEXT_PLAIN ) @Path( "/{nodeId}") publicResponse hello( @PathParam( "nodeId") longnodeId ) { // Do stuff with the database returnResponse.status( Status.OK ).entity( ( "Hello World, nodeId="+ nodeId ).getBytes() ).build(); } } |
范例源代码下载地址: HelloWorldResource.java
编译这些代码,并把编译的jar文件(包括其他任何依赖包)放到 $NEO4J_SERVER_HOME/plugins目录中,包括在 neo4j-server.properties文件中的类。像下面这样:
提示 | ||
确保通过Maven或者 jar -cvf myext.jar *构建的jar文件包括了目录清单,确保用jar目录代替单个文件。 | ||
1 2 | #包含JAXRS资源的JAXRS包被逗号分隔开,一个包名对应一个挂载点。 org.neo4j.server.thirdparty_jaxrs_classes=org.neo4j.examples.server.unmanaged=/examples/unmanaged |
将hello方法绑定到 GET后的地址是: http://{neo4j_server}:{neo4j_port}/examples/unmanaged/helloworld/{nodeId}
1 | curl http://localhost:7474/examples/unmanaged/helloworld/123 |
输出结果:
1 | Hello World, nodeId=123 |
部分 III. 参考
The reference part is the authoritative source for details on Neo4j usage. It covers details on capabilities, transactions, indexing and queries among other topics.
目录
11. 性能
11.1. 数据安全性
11.2. 数据完整性
11.3. 数据集成
11.4. 可用性和可靠性
11.5. 容量
12. 事务管理
12.1. Interaction cycle
12.2. Isolation levels
12.3. Default locking behavior
12.4. Deadlocks
12.5. Delete semantics
12.6. Creating unique nodes
12.7. Transaction events
13. 数据导入
13.1. 批量插入
14. 索引
14.1. Introduction
14.2. Create
14.3. Delete
14.4. Add
14.5. Remove
14.6. Update
14.7. Search
14.8. Relationship indexes
14.9. Scores
14.10. Configuration and fulltext indexes
14.11. Extra features for Lucene indexes
14.12. Automatic Indexing
15. Cypher查询语言
15.1. 操作符
15.2. 表达式
15.3. 参数
15.4. 标识符
15.5. 备注
15.6. 更新图数据库
15.7. 事务
15.8. Patterns
16. 图形算法
16.1. Introduction
17. Neo4j服务器
17.1. 服务器安装
17.2. 服务器配置
17.3. 设置远程调试
17.4. 使用Neo4j服务器(带Web管理控制台)连接一个Neo4j嵌入数据库
17.5. 服务器性能优化
17.6. 在云计算环境中的服务器安装
17.7. Heroku
18. REST API
18.1. Service root
18.2. Streaming
18.3. Cypher queries
18.4. Nodes
18.5. Relationships
18.6. Relationship types
18.7. Node properties
18.8. Relationship properties
18.9. Indexes
18.10. Unique Indexes
18.11. Automatic Indexes
18.12. Configurable Automatic Indexing
18.13. Traversals
18.14. Built-in Graph Algorithms
18.15. Batch operations
18.16. WADL Support
18.17. Cypher插件
18.18. Gremlin Plugin
19. 在Python中使用Neo4j嵌入模式
19.1. 安装
19.2. Core API
19.3. 索引
19.4. Cypher 查询
19.5. 遍历查询