Neo4j 第五篇:批量更新數據


相比圖形數據的查詢,Neo4j更新圖形數據的速度較慢,通常情況下,Neo4j更新數據的工作流程是:每次數據更新都會執行一次數據庫連接,打開一個事務,在事務中更新數據。當數據量非常大時,這種做法非常耗時,大多數時間耗費在連接數據庫和打開事務上,高效的做法是利用Neo4j提供的參數(Parameter)機制和UNWIND子句:在一次數據更新中,進行一次連接,打開一次事務,批量更新數據;參數用於提供列表格式的數據,UNWIND子句是把列表數據展開成一行一行的數據,每行數據都會執行結構相同的Cypher語句。再批量更新圖形數據之前,用戶必須構造結構固定的、參數化的Cypher語句。當Cypher語句的結構相同時,Neo4j數據庫直接從緩存中復用已生成的執行計划,而不需要重新生成,這也能夠提高查詢性能。

除了官方的Neo4j Driver之外,本文分享使用Neo4jClient對圖形數據批量更新,Neo4jClient提供的功能更強大,並支持參數和批量更新操作。

 

我的Neo4j系列的文章收錄在:Neo4j

 

一,參數和UNWIND子句

1,通過RESTful API傳遞參數

Neo4j提供HTTP API處理Cypher語句和參數,在示例代碼中,Neo4j的參數通過HTTP請求傳遞,statement定義的是查詢語句,parameters定義的是參數。

在批量更新數據時,沒有必要發送多個HTTP請求,通過參數,可以在一個HTTP請求(Request)中,開始一個事務,在事務中執行Cypher語句批量更新數據,最后提交該事務。

在發送HTTP請求傳遞參數批量更新數據時,設置HTTP Request的參數如下:

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

注意:在HTTP API中,引用參數的格式是:{param}。

{
  "statements" : [ {
    "statement" : "CREATE (n {props}) RETURN n",
    "parameters" : {
      "props" : {
        "name" : "My Node"
      }
    }
  } ]
}

2,展開(UNWIND)子句

UNWIND子句把列表式的數據展開成一行一行的數據,每一個行都包含更新所需要的全部信息,列表式的數據,可以通過參數來傳遞。

例如,定義參數events,該參數是一個JSON字符串,鍵events是參數名,其值是一個數組,包含兩個數組元素。

{
  "events" : [ {  "year" : 2014, "id" : 1}, {"year" : 2014, "id" : 2 } ]
}   

通過$events引用參數,UNWIND子句把events數組中的兩個元素展開,每個元素執行一次Cypher語句,由於Cypher的語句結構固定,因此,執行計划被緩存起來,在執行數據更新任務時,參數被UNWIND子句展開,復用執行計划,提高數據更新的速度。

UNWIND $events AS event
MERGE (y:Year { year: event.year })
MERGE (y)<-[:IN]-(e:Event { id: event.id })
RETURN e.id AS x
ORDER BY x

二,在Neo4j Browser中使用參數

Neo4j Browser是Neo4j內置的瀏覽器,用於管理數據庫,更新數據庫和查詢數據,再命令窗體中,通過“:”能夠引用內置的命令,例如,通過 ":param"能夠定義參數,並能夠在下一個Cypher語句中引用參數。

1,通過:param命令定義參數

在Neo4j Browser中,輸入第一個命令,通過:param 命令定義參數,

2,通過$param引用參數

緊接着,輸入Cypher語句,通過$param引用參數

3,查看創建的圖形

參數是一個列表格式的數據,在參數events中,兩個event的year屬性都是2014,因此,MERGE子句只會創建一個Year節點;由於兩個event的id屬性不同,因此MERGE子句會創建兩個Event節點,並創建Year節點和Event節點之間的關系,圖形如下圖:

三,使用Neo4jClient批量更新數據

在工程(Projects)中輸入命令安裝Neo4jClient,

Package-Install Neo4jClient

1,連接Neo4j數據庫

創建客戶端,連接到數據庫,創建的Uri的格式是:http://host_name:7474/db/data,並輸入用戶名和密碼,然后創建圖形客戶端,並連接到Neo4j數據庫。

private GraphClient _client;
public Neo4jClientProvider()
{
    _client = new GraphClient(new Uri("http://localhost:7474/db/data"), "user_name", "password");
    _client.Connect();
}

2,批量創建節點

傳遞List<T>參數,通過Unwind函數引用List,並為參數命名為"ns",在Cypher語句中引用參數"ns"

public void CreateNodes(List<DataModel> nodes)
{
    _client.Cypher
        .Unwind(nodes, "ns")
        .Create("(n:NodeLable)")
        .Set("n.NodeID=ns.NodeID")
        .Set("n.Name=ns.Name")
        .ExecuteWithoutResults();
}

2,批量創建關系

在List<T>參數中,傳遞兩個節點的映射,在Neo4j數據庫中,關系必須具有類型,因此,在把參數傳遞到Neo4j數據中時,需要確定兩個節點和關系類型,以創建關系

public bool CreateRelationships(List<RelationshipModel> nodes)
{
    _client.Cypher
        .Unwind(nodes, "ns")
        .Match("(n:Lable1),(s:Lable2)")
        .Where("n.NodeID=ns.NodeID and s.NodeID=ns.RelatedID")
        .Merge("(n)-[r:RelationshipType]->(s)")
        .ExecuteWithoutResults();
}

 

 

 

參考文檔:

3.3.6. UNWIND

Getting Started with Neo4j in .NET with Neo4jClient Library

Batch insert nodes and relations neo4jclient

5 Tips & Tricks for Fast Batched Updates of Graph Structures with Neo4j and Cypher

關於Neo4j和Cypher批量更新和批量插入優化的5個建議


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM