Neo4j - Transactional HTTP endpoint

要讀取、更新、刪除和建立neo4j的node或relationship,可以透過embedded或http的方式,去針對database去操作。

使用http的方式,基本上就是呼叫rest api,db server會依照不同的狀況回傳response status code,同樣也會依照get、post、put、delete去告訴db server,目前要處理方式。

然而neo4j中,提供了很多http的api,可以針對db操作,像是rest api transactionalCypher這類的neo4j rest api

Embedded graph database

透過embedded的方式,會直接在嵌入在你所撰寫的project裡,指定好要儲存的db的path,換句話說,檔案會儲存在server的local端,與以往的mysql、mongodb透過socket的方式不同,有點類似sqlite。

使用embedded的方式,大概會如下方(參考官方):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( "/your_db_path" );

try {
Transaction tx = graphDb.beginTx();

Node firstNode = graphDb.createNode();
firstNode.setProperty( "message", "Hello world" );
System.out.print( firstNode.getProperty( "message" ) );

// Database operations go here
tx.success();

}catch( Exception e ){

//do something
}

Transactional HTTP endpoint

在這簡單介紹Transactional HTTP endpoint,首先neo4j的每個query都會經由transaction機制去處理,所以可以透過已知的transactionid,下一整串的query,最後在決定要rollbackcommit,如果太久沒有commit,neo4j會有個timeout時間(預設60 sec),就會取消先前的query結果。

Begin a transaction

建立一個transaction,之後可以沿用這個transactionid,去執行一連串的query。

官方Example:

Request headers:

1
2
3
POST http://localhost:7474/db/data/transaction
Accept: application/json; charset=UTF-8
Content-Type: application/json

Request json data:

1
2
3
4
5
6
7
8
9
10
{
"statements" : [ {
"statement" : "CREATE (n {props}) RETURN n",
"parameters" : {
"props" : {
"name" : "My Node"
}
}
} ]
}

statements可以一次下多筆query,statement會參照parameters的參數。

Response headers:

1
2
3
201: Created
Content-Type: application/json
Location: http://localhost:7474/db/data/transaction/7

Response json data:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"commit" : "http://localhost:7474/db/data/transaction/7/commit",
"results" : [ {
"columns" : [ "n" ],
"data" : [ {
"row" : [ {
"name" : "My Node"
} ]
} ]
} ],
"transaction" : {
"expires" : "Mon, 03 Feb 2014 13:26:48 +0000"
},
"errors" : [ ]
}

每個response都會回傳一個transactionexpires,這個expires的指的就是transaction的存活時間,而commit這個field包含transactionid,這上面這範例id為7。

Execute statements in an open transaction

使用先前建立transaction,依照transactionid,繼續執行query,若是transaction失效,最後會取得到error messsage。

官方Example:

Request headers:

1
2
3
POST http://localhost:7474/db/data/transaction/7
Accept: application/json; charset=UTF-8
Content-Type: application/json

Request json data:

1
2
3
4
5
{
"statements" : [ {
"statement" : "CREATE n RETURN n"
} ]
}

Response headers:

1
2
200: OK
Content-Type: application/json

Response json data:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"commit" : "http://localhost:7474/db/data/transaction/7/commit",
"results" : [ {
"columns" : [ "n" ],
"data" : [ {
"row" : [ {
} ]
} ]
} ],
"transaction" : {
"expires" : "Mon, 03 Feb 2014 13:26:48 +0000"
},
"errors" : [ ]
}

Execute statements in an open transaction in REST format for the return

在還沒commit之前,只有node會被建立,而建立的propertiesrelationship等的…,一直到commit之後,在database中才有辦法query的到。而REST這個參數,可以幫助你取得目前node間的狀況,response會回傳各種想要查詢的rest api。

官方Example:

Request headers:

1
2
3
POST http://localhost:7474/db/data/transaction/1
Accept: application/json; charset=UTF-8
Content-Type: application/json

Request json data:

1
2
3
4
5
6
{
"statements" : [ {
"statement" : "CREATE n RETURN n",
"resultDataContents" : [ "REST" ]
} ]
}

Response headers:

1
2
200: OK
Content-Type: application/json

Response json data:

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
{
"commit" : "http://localhost:7474/db/data/transaction/1/commit",
"results" : [ {
"columns" : [ "n" ],
"data" : [ {
"rest" : [ {
"paged_traverse" : "http://localhost:7474/db/data/node/12/paged/traverse/{returnType}{?pageSize,leaseTime}",
"labels" : "http://localhost:7474/db/data/node/12/labels",
"outgoing_relationships" : "http://localhost:7474/db/data/node/12/relationships/out",
"traverse" : "http://localhost:7474/db/data/node/12/traverse/{returnType}",
"all_typed_relationships" : "http://localhost:7474/db/data/node/12/relationships/all/{-list|&|types}",
"property" : "http://localhost:7474/db/data/node/12/properties/{key}",
"all_relationships" : "http://localhost:7474/db/data/node/12/relationships/all",
"self" : "http://localhost:7474/db/data/node/12",
"properties" : "http://localhost:7474/db/data/node/12/properties",
"outgoing_typed_relationships" : "http://localhost:7474/db/data/node/12/relationships/out/{-list|&|types}",
"incoming_relationships" : "http://localhost:7474/db/data/node/12/relationships/in",
"incoming_typed_relationships" : "http://localhost:7474/db/data/node/12/relationships/in/{-list|&|types}",
"create_relationship" : "http://localhost:7474/db/data/node/12/relationships",
"data" : {
}
} ]
} ]
} ],
"transaction" : {
"expires" : "Mon, 03 Feb 2014 13:26:44 +0000"
},
"errors" : [ ]
}

Reset transaction timeout of an open transaction

transaction是會過期的,要解決這問題,只要向http://localhost:7474/db/data/transaction/1發送,時效性就會自動延長,若不想下query,只想延長時效。可以發送一個不帶statements內容的的query。

Request headers:

1
2
3
POST http://localhost:7474/db/data/transaction/1
Accept: application/json; charset=UTF-8
Content-Type: application/json

Request json data:

1
2
3
{
"statements" : [ ]
}

Commit an open transaction

要確定存入database,只要commit目前的transaction即可。

Request:

1
2
3
POST http://localhost:7474/db/data/transaction/4/commit
Accept: application/json; charset=UTF-8
Content-Type: application/json

Rollback an open transaction

要取消之前transaction中執行過的query,只要使用rollback即可。

Request:

1
2
DELETE http://localhost:7474/db/data/transaction/3
Accept: application/json; charset=UTF-8

Begin and commit a transaction in one request

如果要執行query後,馬上commit,可以直接透過/db/data/transaction/commit

Request headers:

1
2
3
POST http://localhost:7474/db/data/transaction/commit
Accept: application/json; charset=UTF-8
Content-Type: application/json

Request json data:

1
2
3
4
5
{
"statements" : [ {
"statement" : "CREATE n RETURN id(n)"
} ]
}

Return results in graph format

如果想要查詢節點的圖形結構關係,可以在resultDataContents加入graph這個參數。

Request headers:

1
2
3
POST http://localhost:7474/db/data/transaction/commit
Accept: application/json; charset=UTF-8
Content-Type: application/json

Request json data:

1
2
3
4
5
6
{
"statements" : [ {
"statement" : "CREATE ( bike:Bike { weight: 10 } )CREATE ( frontWheel:Wheel { spokes: 3 } )CREATE ( backWheel:Wheel { spokes: 32 } )CREATE p1 = bike -[:HAS { position: 1 } ]-> frontWheel CREATE p2 = bike -[:HAS { position: 2 } ]-> backWheel RETURN bike, p1, p2",
"resultDataContents" : [ "row", "graph" ]
} ]
}

Response headers:

1
2
200: OK
Content-Type: application/json

Response json data:

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{
"results" : [ {
"columns" : [ "bike", "p1", "p2" ],
"data" : [ {
"row" : [ {
"weight" : 10
}, [ {
"weight" : 10
}, {
"position" : 1
}, {
"spokes" : 3
} ], [ {
"weight" : 10
}, {
"position" : 2
}, {
"spokes" : 32
} ] ],
"graph" : {
"nodes" : [ {
"id" : "17",
"labels" : [ "Wheel" ],
"properties" : {
"spokes" : 3
}
}, {
"id" : "16",
"labels" : [ "Bike" ],
"properties" : {
"weight" : 10
}
}, {
"id" : "18",
"labels" : [ "Wheel" ],
"properties" : {
"spokes" : 32
}
} ],
"relationships" : [ {
"id" : "9",
"type" : "HAS",
"startNode" : "16",
"endNode" : "17",
"properties" : {
"position" : 1
}
}, {
"id" : "10",
"type" : "HAS",
"startNode" : "16",
"endNode" : "18",
"properties" : {
"position" : 2
}
} ]
}
} ]
} ],
"errors" : [ ]
}


Python example

上述對照的request json datarequest headers可參考底下的範例,每個語言使用方式差不多。

dependency

install

1
sudo pip install requests

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests, json       

headers = {
"Accept": "application/json; charset=UTF-8",
"Content-Type": "application/json"
}

data = {
"statements" : [ {
"statement" : "MATCH (n {name: {name}}) RETURN n",
"parameters" : {
"name":"Sparrow"
}
} ]
}

url = "http://localhost:7474/db/data/transaction"

req = requests.post( url , data = json.dumps( data ), headers = headers )

print req.text

可參照官方的Transactional HTTP endpoint,和rest api回傳的status code