Neo4j是一款開源圖數(shù)據(jù)庫,使用Python語言訪問Neo4j可以使用Py2neo。本文介紹了使用Py2neo訪問Neo4j,批量創(chuàng)建節(jié)點和關(guān)系的方法。Py2neo提供了直接執(zhí)行Cypher語句的方法,也提供了諸如Node、Relationship、Path一系列的數(shù)據(jù)結(jié)構(gòu),在不同的場景下可以靈活使用。
?本文使用的Py2neo是2021.1之后的版本,手冊請戳這里:
The Py2neo Handbook
一、安裝Py2neo
使用pip安裝Py2neo,執(zhí)行:
1
|
pip install py2neo |
查看已安裝的Py2neo是什么版本的:
1
|
pip show py2neo |
二、連接Neo4j數(shù)據(jù)庫
本文中會用到多種數(shù)據(jù)類型,在此一并引用
import numpy as np
import pandas as pd
from py2neo import Node,Relationship,Graph,Path,Subgraph
配置Neo4j數(shù)據(jù)庫的訪問地址、用戶名和密碼
1
2
3
|
neo4j_url = '訪問地址' user = '用戶名' pwd = '密碼' |
在此時間段之前訪問數(shù)據(jù)庫的方式為:
1
|
graph = Graph(neo4j_url, username = user, password = pwd) |
在此時間段之后的版本訪問數(shù)據(jù)庫的方式為(就是這么不兼容):
1
|
graph = Graph(neo4j_url, auth=(user, pwd )) |
1. 使用graph.run執(zhí)行Cypher語句創(chuàng)建節(jié)點
如果熟悉Cypher語句的話,可以通過使用graph.run執(zhí)行Cypher語句來實現(xiàn)創(chuàng)建節(jié)點等操作,方法如下所示:
1
2
3
|
cypher_ = "CREATE (:Person {name: '王王' , age:35, work:'服務(wù)器之家}),\ (:Person {name: '李李' , age:20, work:'服務(wù)器之家})" graph.run(cypher_) |
這樣就在Neo4j中創(chuàng)建了兩個label為Person的節(jié)點,第一個節(jié)點的name屬性為“王王”,age屬性為35,work屬性為“服務(wù)器之家”,第二個節(jié)點的name屬性為“李李”,age屬性為20,work屬性為“宇服務(wù)器之家”。
同樣,可以通過調(diào)用graph.run執(zhí)行Cypher語句
創(chuàng)建關(guān)系。
1
2
3
|
cypher_ = "MATCH ( from :Person{name: '王王' }),\ (to:Person{name: '李李' }) MERGE ( from ) - [r:同事] - >(to)" graph.run(cypher_) |
這樣在Neo4j中就有了具有同事關(guān)系的兩個Person節(jié)點。
2. 使用Node數(shù)據(jù)結(jié)構(gòu)創(chuàng)建節(jié)點
Py2neo也提供graph.create方法來創(chuàng)建節(jié)點和關(guān)系
1
2
|
node = Node( "Person" , name = "李李" , age = 20 , work = "服務(wù)器之家" ) graph.create(node) |
與執(zhí)行Cypher語句的效果相同,在Neo4j中創(chuàng)建了一個Person節(jié)點。
需要注意的是,這兩種創(chuàng)建方法,如果反復(fù)執(zhí)行的話,是會在Neo4j中創(chuàng)建出重復(fù)的節(jié)點的,即name、age、work屬性完全一樣,但在Neo4j中的id不一樣的多個節(jié)點。
3. 使用Node、Relationship和Subgraph數(shù)據(jù)結(jié)構(gòu)創(chuàng)建節(jié)點和關(guān)系
上面兩種方法都是一次創(chuàng)建一個節(jié)點或者一個關(guān)系,Py2neo也提供了批量創(chuàng)建節(jié)點和關(guān)系的方法,而且性能更優(yōu)。下面就以下圖中的圖譜為例,使用Py2neo提供Node、Relationship和Subgraph數(shù)據(jù)結(jié)構(gòu)在Neo4j中創(chuàng)建節(jié)點和關(guān)系。
首先創(chuàng)建一些label為Person的節(jié)點,即Node對象,第一個參數(shù)是label,屬性按key=value依次作為參數(shù)傳入。如果節(jié)點有多個label,可以用Node.add_label("label_text")
來追加label。
1
2
3
4
5
6
|
node1 = Node( "Person" , name = "王王" , age = 35 , work = "服務(wù)器之家" ) node2 = Node( "Person" , name = "李李" , age = 20 , work = "服務(wù)器之家" ) node3 = Node( "Person" , name = "張張" , age = 30 , work = "服務(wù)器之家" ) node4 = Node( "Person" , name = "趙趙" , age = 45 , work = "月亮中學(xué)" ) node4.add_label( "Teacher" ) node5 = Node( "Person" , name = "劉劉" , age = 20 , work = "地球電子商務(wù)公司" ) |
再創(chuàng)建一些label為Location的節(jié)點
1
2
3
|
node6 = Node( "Location" , name = "南京" ) node7 = Node( "Location" , name = "江寧區(qū)" ) node8 = Node( "Location" , name = "祿口機場" ) |
建立一些Person和Person節(jié)點之間的關(guān)系,Neo4j中的關(guān)系是有方向的,所以Relationship第一個參數(shù)為起始節(jié)點,第三個參數(shù)是結(jié)束節(jié)點,而第二個節(jié)點為關(guān)系的類型。這里創(chuàng)建的同事、鄰居的關(guān)系為雙向的,老師、學(xué)生的關(guān)系為單向。
1
2
3
4
5
6
7
8
9
10
11
|
relation1 = Relationship(node1, "同事" , node2) relation2 = Relationship(node2, "同事" , node1) relation3 = Relationship(node2, "同事" , node3) relation4 = Relationship(node3, "同事" , node2) relation5 = Relationship(node3, "鄰居" , node4) relation6 = Relationship(node4, "鄰居" , node3) relation7 = Relationship(node4, "學(xué)生" , node5) relation8 = Relationship(node5, "老師" , node4) |
創(chuàng)建一些Location和Location節(jié)點之間的關(guān)系,地域之間的包含關(guān)系為單向。
1
2
|
relation9 = Relationship(node6, "包含" , node7) relation10 = Relationship(node7, "包含" , node8) |
創(chuàng)建Person節(jié)點和Location節(jié)點之間的關(guān)系,這里“到訪”的關(guān)系是有屬性的,date表示到訪的日期,stay_hours表示停留的時間??梢允褂靡粋€key:value的字典數(shù)據(jù)結(jié)構(gòu)保存屬性,再賦予關(guān)系
1
2
3
4
5
|
properties1 = { 'date' : '2021-7-16' , 'stay_hours' : 1 } relation11 = Relationship(node2, "到訪" , node8, * * properties1) properties2 = { 'date' : '2021-7-19' , 'stay_hours' : 4 } relation12 = Relationship(node5, "到訪" , node8, * * properties2) |
然后將以上所有節(jié)點和關(guān)系組成Subgraph
1
2
3
4
5
6
|
node_ls = [node1, node2, node3, node4, node5, node6, node7, node8] relation_ls = [relation1, relation2, relation3, relation4, relation5, relation6, relation7, relation8, relation9, relation10, relation11, relation12] subgraph = Subgraph(node_ls, relation_ls) |
最后通過事務(wù)類Transaction提交,批量創(chuàng)建這些節(jié)點和關(guān)系。這里tx.create并沒有真正創(chuàng)建節(jié)點和關(guān)系,直到graph.commit才一次性提交到Neo4j進行創(chuàng)建。
1
2
3
|
tx = graph.begin() tx.create(subgraph) graph.commit(tx) |
重復(fù)執(zhí)行上面的命令,不會創(chuàng)造出重復(fù)的節(jié)點和關(guān)系。這一點手冊中有說明:“subgraph中的已經(jīng)和數(shù)據(jù)庫綁定的實體將保持不變,那些沒有綁定的將在數(shù)據(jù)庫中新建并綁定上。”
create(subgraph) Create remote nodes and relationships that correspond to those in a local subgraph. Any entities in subgraph that are already bound to remote entities will remain unchanged, those which are not will become bound to their newly-created counterparts.
三、性能對比
做一個簡單的實驗粗略地對比逐個創(chuàng)建和批量創(chuàng)建的時間開銷。在Neo4j為空數(shù)據(jù)庫的情況下,分別采用逐個創(chuàng)建和批量創(chuàng)建的方法創(chuàng)建10000個節(jié)點,每個節(jié)點有name和age兩個屬性,都是隨機生成的,使用jupyter notebook的%%time命令計算時間開銷。
1
2
|
import random N = 10000 |
逐個創(chuàng)建節(jié)點:
1
2
3
4
5
6
7
8
9
|
% % time for i in range (N): random_name = "P" + str ( round (random.random() * N * 2 )) random_age = round (random.random() * 15 ) node = Node( "Person" , name = random_name, age = random_age) graph.create(node) CPU times: user 50.3 s, sys: 4.19 s, total: 54.5 s Wall time: 5min 16s |
批量創(chuàng)建節(jié)點:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
% % time node_ls = [] for i in range (N): random_name = "P" + str ( round (random.random() * N * 2 )) random_age = round (random.random() * 15 ) node = Node( "Person" , name = random_name, age = random_age) node_ls.append(node) subgraph = Subgraph(node_ls, []) tx = graph.begin() tx.create(subgraph) graph.commit(tx) CPU times: user 448 ms, sys: 75.5 ms, total: 523 ms Wall time: 1.46 s |
實驗中也發(fā)現(xiàn),只是創(chuàng)建節(jié)點的話,批量創(chuàng)建方法的時間開銷幾乎是線性增長的,當(dāng)一次性提交10萬個節(jié)點的創(chuàng)建任務(wù)時,時間開銷大約在4.5秒。
在使用Py2neo構(gòu)建圖譜時,盡可能使用批量創(chuàng)建方法。先創(chuàng)建節(jié)點(Node)對象、關(guān)系(Relationship)對象,再構(gòu)成子圖(Subgraph),最后利用事務(wù)類一次提交創(chuàng)建。
下一篇將介紹如何運用Py2neo查詢節(jié)點、關(guān)系和路徑。
這篇關(guān)于用Py2neo創(chuàng)建Neo4j的節(jié)點、關(guān)系及路徑的文章就先介紹到這了,更多相關(guān)Py2neo內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://segmentfault.com/a/1190000040519140