py2neo——Neo4j&python的配合使用

概要
之前在CSDN上寫過一個blog(http://blog.csdn.net/wrzcy/article/details/51905977 ),簡單的介紹了Neo4j圖形數據庫,主要是以基礎概念和定義爲主。今天就通過python面向Neo4j的庫py2neo來對Neo4j進行一些簡單的操作,包括:

連接Neo4j數據庫
節點的建立
節點之間關係的建立
關係屬性賦值以及屬性值的更新
通過屬性值查找節點/關係
通過節點/關係查找相關聯的節點/關係
結合目前的一個項目來說說一些坑和注意點
連接Neo4j數據庫
要通過python來操作Neo4j,首先需要安裝py2neo,可以直接使用pip安裝。

pip install py2neo
在完成安裝之後,在python中調用py2neo即可,常用的有Graph,Node,Relationship。

from py2neo import Graph,Node,Relationship
連接Neo4j的方法很簡單:

test_graph = Graph(
"http://localhost:7474",
username="neo4j",
password="neo4j"
)
test_graph就是我們建立好的Neo4j的連接。
Neo4j的服務器裝好了之後,默認的端口號就是7474,所以本地的主機就是"http://localhost:7474" 。
默認的用戶名密碼都是neo4j,不過也可以在瀏覽器中進入http://localhost:7474 ,首次進入會提示你進行密碼修改。

節點的建立
節點的建立要用到py2neo.Node,建立節點的時候要定義它的節點類型(label)以及一個基本屬性(property,包括property_key和property_value)。以下代碼爲建立了兩個測試節點。

test_node_1 = Node(label = "Person",name = "test_node_1")
test_node_2 = Node(label = "Person",name = "test_node_2")
test_graph.create(test_node_1)
test_graph.create(test_node_2)
這兩個節點的類型(label)都是Person,而且都具有屬性(property_key)爲name,屬性值(property_value)分別爲"test_node_1","test_node_2"。

節點間關係的建立
節點間的關係(Relationship)是有向的,所以在建立關係的時候,必須定義一個起始節點和一個結束節點。值得注意的是,起始節點可以和結束節點是同一個點,這時候的關係就是這個點指向它自己。

node_1_call_node_2 = Relationship(test_node_1,'CALL',test_node_2)
node_1_call_node_2['count'] = 1
node_2_call_node_1 = Relationship(test_node_2,'CALL',test_node_1)
node_2_call_node_1['count'] = 2
test_graph.create(node_1_call_node_2)
test_graph.create(node_2_call_node_1)
如以上代碼,分別建立了test_node_1指向test_node_2和test_node_2指向test_node_1兩條關係,關係的類型爲"CALL",兩條關係都有屬性count,且值爲1。

在這裏有必要提一下,如果建立關係的時候,起始節點或者結束節點不存在,則在建立關係的同時建立這個節點。

節點/關係的屬性賦值以及屬性值的更新
節點和關係的屬性初始賦值在前面節點和關係的建立的時候已經有了相應的代碼,在這裏主要講述一下怎麼更新一個節點/關係的屬性值。

我們以關係建立裏的 node_1_call_node_2 爲例,讓它的count加1,再更新到圖數據庫裏面。

node_1_call_node_2['count']+=1
test_graph.push(node_1_call_node_2)
更新屬性值就使用push函數來進行更新即可。

通過屬性值來查找節點和關係(find,find_one)
通過find和find_one函數,可以根據類型和屬性、屬性值來查找節點和關係。
示例如下:

find_code_1 = test_graph.find_one(
label="Person",
property_key="name",
property_value="test_node_1"
)
print find_code_1['name']
find和find_one的區別在於:
find_one的返回結果是一個具體的節點/關係,可以直接查看它的屬性和值。如果沒有這個節點/關係,返回None。
find查找的結果是一個遊標,可以通過循環取到所找到的所有節點/關係。

通過節點/關係查找相關聯的節點/關係
如果已經確定了一個節點或者關係,想找到和它相關的關係和節點,就可以使用match和match_one。

find_relationship = test_graph.match_one(start_node=find_code_1,end_node=find_code_3,bidirectional=False)
print find_relationship
如以上代碼所示,match和match_one的參數包括start_node,Relationship,end_node中的至少一個。

bidirectional參數的意義是指關係是否可以雙向。
如果爲False,則起始節點必須爲start_node,結束節點必須爲end_node。如果有Relationship參數,則一定按照Relationship對應的方向。
如果爲True,則不需要關心方向問題,會把兩個方向的數據都返回。

match_relation = test_graph.match(start_node=find_code_1,bidirectional=True)
for i in match_relation:
print i
i['count']+=1
test_graph.push(i)
如以上代碼所示,查找和find_code_1相關的關係。
match裏面的參數只寫了start_node,bidirectional的值爲True,則不會考慮方向問題,返回的是以find_code_1爲起始節點和結束節點的所有關聯關係。
如果,bidirectional的值爲False,則只會返回以find_code_1爲起始節點的所有關聯關係。

結合項目淺談Neo4j裏值得注意的地方
寫這篇blog主要也是因爲最近再做一個關係查找的數據庫,在使用Neo4j的時候還是自己挖了不少坑愉快的跳了下去然後到處掙扎。不過大部分的情況下終歸還是能爬出來,在這裏把遇到的一些問題和值得注意的地方分享出來,希望別人不要走我的老路。

關於節點和關係的建立
建立節點和關係之前最好先查找一下是否已經存在這個節點了。如果已經存在的話,則建立關係的時候使用自己查找到的這個節點,而不要新建,否則會出現一個新的節點。

如果一條條建立關係和節點的話,速度並不快。如果條件合適的話,最好還是用Neo4j的批量導入功能。不過因爲在本項目裏面並不適合使用批量導入功能,所以只能一條條的插入。

關於索引
在Neo4j 2.0版本以後,儘量使用schema index,而不要使用舊版本的索引。

最好在插入數據之前就建立好索引,否則索引的建立會很消耗時間。

索引建立是非常有必要的,一個索引可以很大程度上降低大規模數據的查詢速度。

以我自己爲例,這次做項目的時候因爲第一次沒有加入索引,當數據規模達到4w節點,7w+關係的時候,查詢一個節點以及相關聯的節點關係所消耗的時間已經達到了1s。

在對節點按照name屬性建立了索引之後,截止我寫這篇blog的時候,數據量爲節點600w+,關係1100w+,查詢一個節點以及相關聯的節點關係消耗的時間和數據量很小的時候幾乎沒有什麼差別,基本上都穩定在16~20ms左右。

關於Neo4j應當插入的數據內容
我們在使用圖數據庫的時候必須要明確一點,圖數據庫能夠幫助我們的是以儘量快的速度找出來不同的節點之間的關係。因此向一個節點或者關係裏面插入很多其餘無關的數據是完全沒有必要的,會很大程度浪費硬盤資源,在檢索的時候也會消耗更多的時間。

仍舊是以我這次的項目爲例。截止到寫這篇blog時已經向裏面導入了2w條原始數據,我導入的每條數據中,有大量的跟關聯關係無關的其他數據,但是這些都是沒有必要的冗餘數據,完全不需要向Neo4j裏面插入。

在最後我設計的圖數據庫裏,節點類型爲Person,每個節點只有一個屬性name,標誌這個節點。每兩個節點之間最多隻會有一來一回兩條關係,表示主從關係。

通過這樣的圖,我們想要檢索任何節點的關聯節點都可以很快速的找到,而且可以很清楚的區分哪些節點的聯繫比較緊密。

如果要把其他的不必要的數據插入進去,跟2w條原始數據對應的600w+的節點和1100w+的關係,必然會佔用大量的存儲空間,也會大幅增加查詢的時間。

所以務必牢記,圖數據庫的本質是爲了方便查找不同的人或者事物之間的關係的,而不是爲了存儲數據的。

https://www.jianshu.com/p/a2497a33390f

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章