2016-12-24 142 views
2

我需要在Neo4j中創建一個二叉樹。我已經開始創建兩個CSV,一個用於頂點,一個用於邊緣,然後我啓動了兩個查詢來創建整個樹。從CSV加載創建二叉樹

我認爲我可以創建只有一個查詢整個樹。 從我開始在CSV是這樣的:

"parent","child_1","child_1_attr1","child_1_attr2","edge_1_attr1","edge_1_attr2","child_2","child_2_attr1","child_2_attr2","edge_2_attr1","edge_2_attr2" 
"vertex_1","vertex_2","2","5","4","1","vertex_3","5","3","2","2" 
"vertex_2","vertex_4","3","5","2","3","vertex_5","4","4","4","3" 
"vertex_3","vertex_6","2","1","2","4","vertex_7","2","2","5","5" 
"vertex_4","vertex_8","4","4","4","5","vertex_9","2","3","2","5" 
"vertex_5","vertex_10","1","1","3","3","vertex_11","1","3","2","3" 
"vertex_6","vertex_12","3","1","1","1","vertex_13","1","2","5","1" 
"vertex_7","vertex_14","4","2","2","1","vertex_15","2","5","4","3" 

然後我嘗試此查詢:

LOAD CSV WITH HEADERS FROM 'file:///Prova1.csv' AS line 
Match (p:Vertex {name: line.parent}) 
Create (c1:Vertex {name: line.child_1, attr1: line.child_1_attr1, attr2: line.child_1_attr2}) 
Create (c2:Vertex {name: line.child_2, attr1: line.child_2_attr1, attr2: line.child_2_attr2}) 
Create (p)<-[:EDGE {attr1: line.edge_1_attr1, attr2: line.edge_1_attr2}]-(c1) 
Create (p)<-[:EDGE {attr1: line.edge_2_attr1, attr2: line.edge_2_attr2}]-(c2) 

此查詢我手動創建的第一個頂點之前,和我運行此查詢,但只結果是我得到的是Vertices 1,2和3的創建。 它應該匹配父(始終已經創建),然後創建兩個孩子,然後它應該將這兩個孩子連接到他的父親。

誰能幫幫我?

回答

1

對於每行/每行,可能您的執行視圖執行所有的Cypher代碼,然後重複執行下一行/行直到完成,這是不正確的。

相反,每一個人的Cypher操作將執行所有行,那麼接下來的Cypher操作將所有行執行等

這意味着你的匹配操作:

Match (p:Vertex {name: line.parent})

執行跨越CSV中的所有行,然後纔會進入下一個操作(您的CREATE,在所有行上執行),等等。

由於您聲明手動創建了第一個頂點,該頂點是唯一可匹配的頂點,因此您的CSV中的所有其他行都將失敗,因爲CREATE語句尚未執行,因此這些節點不存在。這意味着只會創建兩個頂點,它們的子節點完全匹配節點。

導入CSV數據首先創建所有節點,然後使用單獨的CSV處理來匹配已創建的節點並創建相關關係時,這通常是一種很好的做法。然而,如果你確實想要在一個目標中創建所有東西,你可能會想在各個地方使用MERGE,但是如果你不完全理解MERGE的行爲,這也是非常棘手的(這就像是一次嘗試MATCH,如果找不到匹配,CREATE)或者不完全理解Cypher是如何執行的(如本例中那樣)。

您還需要根據唯一節點值而不是所有屬性合併,並設置其餘屬性。在相關標籤/屬性上使用唯一約束或索引(無論哪個都適合)以加快執行速度,特別是隨着圖形大小的增長,這也特別有用。

此查詢可能有效。

LOAD CSV WITH HEADERS FROM 'file:///Prova1.csv' AS line 
MERGE (p:Vertex {name: line.parent}) 
MERGE (c1:Vertex {name: line.child_1}) 
SET c1.attr1 = line.child_1_attr1, c1.attr2 = line.child_1_attr2 
MERGE (c2:Vertex {name: line.child_2}) 
SET c2.attr1 = line.child_2_attr1, c2.attr2 = line.child_2_attr2 
Create (p)<-[:EDGE {attr1: line.edge_1_attr1, attr2: line.edge_1_attr2}]-(c1) 
Create (p)<-[:EDGE {attr1: line.edge_2_attr1, attr2: line.edge_2_attr2}]-(c2) 

這一個工程的原因是,到時候你第一次完成合併爲你的圖表的父節點,將已創建的所有父節點(或者更確切地說,節點,這將是父母)。

所以,當我們到達你的子節點的MERGE時,這將會匹配你圖中已經創建的節點的大部分......在那個點上將創建的唯一新節點將是葉節點,由您的第一個MERGE創建,因爲它們不會成爲其他任何節點的父母,並且不會顯示在您的CSV的父列中。

+0

首先,感謝對Cypher代碼執行的詳細解釋,這是非常有用的,因爲我正在通過我自己的Neo4j學習大學項目很難找到像這樣簡單的解釋。 –

+0

順便說一句,前幾天我設法創建一個單一的查詢樹和像這樣的小的,它的工作原理。事實是,我需要管理至少有2百萬個節點的樹,並且我正在考慮使用這種方法來改進創建帶有2個CSV(一個用於節點,一個用於邊)的2M節點樹,在這種情況下需要300秒(在通用筆記本電腦上使用 '使用定期COMMIT')。 你認爲用你的查詢'使用週期性提交'會起作用嗎?而且,你認爲這個查詢實際上可以縮短創建時間嗎? –

+0

使用週期性COMMIT應該可以提高導入性能,並且您絕對需要一個唯一的約束:頂點(名稱)(或者至少一個索引,如果名稱不是唯一的頂點)。如果使用2個CSV,其中一個用於節點,另一個用於邊緣,則可以在關係CSV中的頂點上自由使用MATCH而不是MERGE,並且可以在節點之間自行創建CREATE,這應該有助於提高性能。 – InverseFalcon

0

由於某種原因導入查詢不起作用,因爲您先匹配父項,然後創建節點和關係。我修改查詢這樣的,它現在的工作:所以

LOAD CSV WITH HEADERS FROM 'file:///test.csv' AS line 
CREATE (c1:Vertex {name: line.child_1, attr1: line.child_1_attr1, attr2: line.child_1_attr2}), 
     (c2:Vertex {name: line.child_2, attr1: line.child_2_attr1, attr2: line.child_2_attr2}) WITH c1,c2, line 
MATCH (p:Vertex {name:line.parent}) CREATE (p)<-[:EDGE {attr1: line.edge_1_attr1, attr2: line.edge_1_attr2}]-(c1), 
     (p)<-[:EDGE {attr1: line.edge_2_attr1, attr2: line.edge_2_attr2}]-(c2) 

如果先創建節點,然後匹配父和創建查詢工作的關係。結果是這樣的:

enter image description here

我將探討您的查詢找到一個理由,爲什麼它不工作,因爲我真的不明白爲什麼它不工作。

+0

感謝您的幫助...這是我在失敗後寫的。解釋爲什麼我的查詢不起作用在下一個答案:) –

0
foreach (num in range(1,15) | 
merge (parent:Node {number: num}) 
merge (left:Node {number: num + num}) 
merge (right:Node {number: num + num + 1}) 
merge (left)<-[:LEFT]-(parent)-[:RIGHT]->(right) 
) 

說明: 這將創建一個完美的二叉樹結構與31個節點。然後,您可以在CSV中包含相同的編號,以查找和添加屬性到每個對應編號的節點。

在二叉樹中,如果在值爲1的第一個(根或最上方的節點)上包含數字屬性,則將每個後續節點的數值增加1(從左到右;從上到下)方便的數學關係,其中每個節點的左邊孩子的父母的數字+數字的數字值,右邊的孩子是數字+數字+ 1.