neo4j REST API

2.3.1.1. 从Java中使用REST API创建一张图

REST API使用 HTTP协议传输,数据采用JSON格式,以至于他能被需要计算机语言和平台使用。尽管如此,准备开始使用之前,看一些可以重用的模式是非常有用的。在这 个简短的概述中,我们将为你展示如何通过REST API创建一个或者多个简单图并且查询他里面存在的数据。

为了得到这些范例,我们选择了 Jersey 客户端组件,他可以通过Maven轻松下载

2.3.1.2. 启动 Neo4j 服务端

在我们准备在Neo4j服务端做任何操作之前,我们需要先启动他,可以参考:3.7.1. 数据库服务端安装

WebResource resource = Client.create()
         .resource( SERVER_ROOT_URI );
ClientResponse response = resource.get( ClientResponse. class );
System.out.println( String.format( "GET on [%s], status code [%d]" ,
         SERVER_ROOT_URI, response.getStatus() ) );
response.close();

如果返回的状态码是200 OK, 那我们就确定 Neo4j 服务端已经成功运行,我们可以继续使用了。如果连接到服务端失败,请参考:3.7. Neo4j数据库服务端

注意
[Note]
如果你获得的返回码大于200 OK (特别是 4xx 或者 5xx ),那请您检查你的配置并查看在目录data/log中的日志。

2.3.1.3. 创建一个节点

REST API 使用 POST 来创建节点. 在Java中封装的接口使用Jersey客户端便可以非常容易使用:

final String nodeEntryPointUri = SERVER_ROOT_URI + "node" ;
WebResource resource = Client.create()
         .resource( nodeEntryPointUri );
// POST {} to the node entry point URI
ClientResponse response = resource.accept( MediaType.APPLICATION_JSON )
         .type( MediaType.APPLICATION_JSON )
         .entity( "{}" )
         .post( ClientResponse. class );
final URI location = response.getLocation();
System.out.println( String.format(
         "POST to [%s], status code [%d], location header [%s]" ,
         nodeEntryPointUri, response.getStatus(), location.toString() ) );
response.close();
return location;

如果调用成功完成,他会在后台发送一个包含JSON数据的HTTP请求给服务端。服务端会在数据库中创建一个新的节点并且返回状态码 201 Created 和访问这个新节点的地址

在我们的范例中,我们将调用这个功能两次以便在数据库中创建两个节点。

2.3.1.4. 为节点增加属性

一旦我们在数据库中有了节点,我们可以使用他们来保存有用的数据。在这个范例中,我们将在我们的数据库中保存音乐信息。下面让我们浏览下面的代码, 代码中,我们创建了节点并且给节点增加属性。这里,我们新增一个节点“Joe Strummer”,并且增加了一个属性 “brand”,属性值是: “The Clash”。

URI firstNode = createNode();
addProperty( firstNode, "name" , "Joe Strummer" );
URI secondNode = createNode();
addProperty( secondNode, "band" , "The Clash" );

在方法addProperty内部,我们确定了代表节点属性的名称,以及该属性的值。然后我们使用PUT将该属性发送到服务端。

String propertyUri = nodeUri.toString() + "/properties/" + propertyName;
// http://localhost:7474/db/data/node/{node_id}/properties/{property_name}
WebResource resource = Client.create()
         .resource( propertyUri );
ClientResponse response = resource.accept( MediaType.APPLICATION_JSON )
         .type( MediaType.APPLICATION_JSON )
         .entity( "\"" + propertyValue + "\"" )
         .put( ClientResponse. class );
System.out.println( String.format( "PUT to [%s], status code [%d]" ,
         propertyUri, response.getStatus() ) );
response.close();

如果一切顺利,我们将会得到返回码:204 No Content,表示服务端已经受理这个请求,整个请求不会回显属性的值。

2.3.1.5. 为节点增加关系

现在我们有了表示Joe Strummer 和 The Clash的节点,我们可以关联他们。REST API通过一个POST方式支持对节点建立关系。在Java中相应地,我们POST>一些JSON到节点Joe Strummer的节点地址,确定了该节点和The Clash节点之间的关系。

URI relationshipUri = addRelationship( firstNode, secondNode, "singer" ,
         "{ \"from\" : \"1976\", \"until\" : \"1986\" }" );

addRelationship方法中,我们确定了Joe Strummer节点的地址,然后POST一些JSON数据从而建立关系。这些JSON数据包括目标节点,关系的类型以及一些关系的属性等。

private static URI addRelationship( URI startNode, URI endNode,
         String relationshipType, String jsonAttributes )
         throws URISyntaxException
{
     URI fromUri = new URI( startNode.toString() + "/relationships" );
     String relationshipJson = generateJsonRelationship( endNode,
             relationshipType, jsonAttributes );
     WebResource resource = Client.create()
             .resource( fromUri );
     // POST JSON to the relationships URI
     ClientResponse response = resource.accept( MediaType.APPLICATION_JSON )
             .type( MediaType.APPLICATION_JSON )
             .entity( relationshipJson )
             .post( ClientResponse. class );
     final URI location = response.getLocation();
     System.out.println( String.format(
             "POST to [%s], status code [%d], location header [%s]" ,
             fromUri, response.getStatus(), location.toString() ) );
     response.close();
     return location;
}

如果一切正常,我们将得到返回码:201 Created和一个地址Location,这个地址是我们刚建立的关系的地址。

2.3.1.6. 为关系增加一个属性

像节点一样,管东西一样拥有属性。自从我们大量关注Joe Strummer和 The Clash以来,我们增加了他们的关系的属性:等级,以至于我们可以看到一个五星级的品牌属性。

addMetadataToProperty( relationshipUri, "stars" , "5" );

addMetadataToProperty方法中,我们确定了关系的地址,然后PUT我们新的值到服务端,这些新的值会覆盖过去已经存在的,所以请在操作之前务必谨慎。

private static void addMetadataToProperty( URI relationshipUri,
         String name, String value ) throws URISyntaxException
{
     URI propertyUri = new URI( relationshipUri.toString() + "/properties" );
     String entity = toJsonNameValuePairCollection( name, value );
     WebResource resource = Client.create()
             .resource( propertyUri );
     ClientResponse response = resource.accept( MediaType.APPLICATION_JSON )
             .type( MediaType.APPLICATION_JSON )
             .entity( entity )
             .put( ClientResponse. class );
     System.out.println( String.format(
             "PUT [%s] to [%s], status code [%d]" , entity, propertyUri,
             response.getStatus() ) );
     response.close();
}

假设一切正常,我们将得到返回码:200 OK(我们也可以通过调用ClientResponse.getStatus()来检查),到此,我们已经建立起了一个小型的图数据库网络,我们已经可以从中查询一些有价值的数据了。

2.3.1.7. 查询

跟图数据嵌入模式一样,Neo4j服务端模式也使用图遍历来查询数据。当前,Neo4j服务端希望得到一个JSON格式的查询请求通过POST发送给他以便遍历数据库。(虽然这在以GET方式传送的适合随时都会发生变化)。

为了启动这个查询,我们使用了一个能做JSON转换的类,准备POST数据到服务端。在这种情况下,我们硬编码到遍历查询条件中,查找所有有类型是"singer"的输出关系的节点。

// TraversalDescription turns into JSON to send to the Server
TraversalDescription t = new TraversalDescription();
t.setOrder( TraversalDescription.DEPTH_FIRST );
t.setUniqueness( TraversalDescription.NODE );
t.setMaxDepth( 10 );
t.setReturnFilter( TraversalDescription.ALL );
t.setRelationships( new Relationship( "singer" , Relationship.OUT ) );

一旦我们确定了遍历的参数,我们只需要转换它。我们确定了遍历的开始节点,然后POST JSON数据到服务端开始查询。

URI traverserUri = new URI( startNode.toString() + "/traverse/node" );
WebResource resource = Client.create()
         .resource( traverserUri );
String jsonTraverserPayload = t.toJson();
ClientResponse response = resource.accept( MediaType.APPLICATION_JSON )
         .type( MediaType.APPLICATION_JSON )
         .entity( jsonTraverserPayload )
         .post( ClientResponse. class );
System.out.println( String.format(
         "POST [%s] to [%s], status code [%d], returned data: "
                 + System.getProperty( "line.separator" ) + "%s" ,
         jsonTraverserPayload, traverserUri, response.getStatus(),
         response.getEntity( String. class ) ) );
response.close();

一旦这个请求完成,我们将得到我们的歌手的数据集以及他们属于的品牌:

[ {
   "outgoing_relationships" : "http://localhost:7474/db/data/node/82/relationships/out" ,
   "data" : {
     "band" : "The Clash" ,
     "name" : "Joe Strummer"
   },
   "traverse" : "http://localhost:7474/db/data/node/82/traverse/{returnType}" ,
   "all_typed_relationships" : "http://localhost:7474/db/data/node/82/relationships/all/{-list|&|types}" ,
   "outgoing_typed_relationships" : "http://localhost:7474/db/data/node/82/relationships/out/{-list|&|types}" ,
   "incoming_relationships" : "http://localhost:7474/db/data/node/82/relationships/in" ,
   "incoming_typed_relationships" : "http://localhost:7474/db/data/node/82/relationships/in/{-list|&|types}" ,
}, {
   "outgoing_relationships" : "http://localhost:7474/db/data/node/83/relationships/out" ,
   "data" : {
   },
   "traverse" : "http://localhost:7474/db/data/node/83/traverse/{returnType}" ,
   "all_typed_relationships" : "http://localhost:7474/db/data/node/83/relationships/all/{-list|&|types}" ,
   "outgoing_typed_relationships" : "http://localhost:7474/db/data/node/83/relationships/out/{-list|&|types}" ,
   "incoming_relationships" : "http://localhost:7474/db/data/node/83/relationships/in" ,
   "incoming_typed_relationships" : "http://localhost:7474/db/data/node/83/relationships/in/{-list|&|types}" ,
} ]

2.3.1.8. 呼,是它吗?

这就是我们使用REST API的方式。自然对于对HTTP协议不了解的,我们提供了对HTTP操作的封装,包括通过DELETE移除节点和关系。当然,如果你想了解更多,你可以尝试在Jersey客户端代码中采用.post()来代替.delete()

2.3.1.9. 下一步做什么呢?

HTTP API 提供了大量客户端基本操作的实现,也包括HTTP和REST。在将来,虽然 REST API的方式占有一定的优势,但是我们还是期望出现语言级的方式来做客户端,能更轻松的绑定到Neo4j的嵌入模式(比如python)。关于当前 Neo4j REST客户端以及嵌入封装,请查看:http://www.delicious.com/neo4j/drivers

http://www.neo4j.org.cn/2012/07/30/server-java-rest-client-example/#maodian001

http://docs.neo4j.org.cn/

猜你喜欢

转载自m635674608.iteye.com/blog/2291835