2014-02-11 74 views
2

我想用Cypher over REST創建一個鏈表。Neo4j - 你如何通過Cypher通過REST並行插入鏈表?

如果我使用下面的查詢創建列表的頭:

MERGE (headNode:HEAD {list:"mylist"}) 
WITH headNode 
MERGE headNode-[:LINK]->(headNode) 
RETURN headNode 

然後執行使用此查詢插入:

MERGE (headNode:HEAD {list:"mylist"})-[old:LINK]->after 
DELETE old 
CREATE headNode-[:LINK]->(newNode:LINKNODE { number : {nodeNumber} })-[:LINK]->after 

然後一切都很好,只要我不併行運行多個插入查詢。但是當我這樣做時,我開始得到不好的後果。我得到(取決於時間)一個錯誤,如:

Error: Relationship 391112 not found 

或者我得到多個鏈接列表蛇行出頭節點。我已經建立了一個複製問題here的測試node.js項目。

如何在Neo4j中創建一個可以處理並行插入的鏈表?

回答

2

我建議不要試圖猜測鎖定是如何工作的。相反,我們可以利用我們掌握的更好的文檔工具和功能來構建一些東西。

假設我們有這樣一個獨特的約束:

create constraint on (n:LINK) assert n.list_head_id is unique 
; 

然後,我們可以同時插入在列表的頭部(在此過程中可能會創建它)是這樣的:

merge (current_head:LINK {list_head_id: {list_id}}) 
on create set current_head.is_sentinel = true 
remove current_head.list_head_id 
create (new_head:LINK {list_head_id: {list_id}})-[:NEXT]->current_head 
; 

這列表總是以一個標記鏈接結尾,所以當你查詢它時你需要忽略它。

現在,上述情況會產生會導致事務失敗的死鎖異常。潛在的很多。因此,您需要確保重試那些因死鎖而失敗的事務。

我用Java寫了自己的測試來演示這種方法。請注意,在此測試中,我在事務之間引入了一個小的隨機延遲,以減少死鎖的可能性。這是因爲測試使用的是嵌入式數據庫,所以沒有任何網絡或任何東西可以限制併發性的數量和速度:https://gist.github.com/chrisvest/9033600

+0

謝謝克里斯,非常感激你的這個答案。 –

+0

CREATE CONSTRAINT ... – jonincanada

+0

謝謝,jonincanada –

2

爲了做到並行插入你需要採取的鎖有問題的節點(或多個):

MATCH (headNode:HEAD {list:"mylist"})-[old:LINK]->after 
REMOVE headNode._lock_ 
REMOVE after._lock_ 
DELETE old 
CREATE headNode-[:LINK]->(newNode:LINKNODE { number : {nodeNumber} })-[:LINK]->after 
RETURN headNode, newNode 

REMOVE headNode._lock_ 
REMOVE after._lock_ 

刪除一個不存在的屬性,當財產被刪除鎖定被採取。現在,如果由於鎖定而無法插入查詢,您將得到一個Neo.DatabaseError.Statement.ExecutionFailure這意味着插入失敗,您可以重新運行查詢。

+0

經過進一步的研究,我發現這種方法不起作用,鎖不正確 –

+0

嗨,你有沒有找到任何解決方案? – tubu13

+0

沒有抱歉,我沒有。這令人難以置信的刺激,我花了數週時間。你有沒有嘗試接受的答案?我不記得它是這樣標記的。 –