py2neo V4 極簡(jiǎn)使用指南:Python操作Neo4j圖數(shù)據(jù)庫(kù)

Neo4j的介紹可以參考這篇文章:《知識(shí)圖譜技術(shù)與應(yīng)用指南(轉(zhuǎn))》

其實(shí),Python操作Neo4j,既可以用neo4j也可以用py2neo,前者是Neo4j官方的api,但是py2neo開(kāi)發(fā)地更早,已經(jīng)到V4了。

官方文檔地址:https://py2neo.org/v4/


0、安裝

下載Neo4j:https://neo4j.com/download/

使用pip安裝: pip install py2neo

從github源碼安裝:pip install git+https://github.com/technige/py2neo.git#egg=py2neo


1、數(shù)據(jù)類(lèi)型

1.1 節(jié)點(diǎn)Node和關(guān)系Relationship對(duì)象

圖數(shù)據(jù)庫(kù),最重要的就是節(jié)點(diǎn)、邊和屬性,py2neo中最重要的就是類(lèi)NodeRelationship

from py2neo.data import Node, Relationship
a = Node("Person", name="Alice")
b = Node("Person", name="Bob")
ab = Relationship(a, "KNOWS", b)
print(ab)
# (Alice)-[:KNOWS]->(Bob)

如果沒(méi)有指定節(jié)點(diǎn)之間的關(guān)系,則默認(rèn)為TO。也可以自建類(lèi)Relationship的子類(lèi),如下:

c = Node("Person", name="Carol")
class WorksWith(Relationship): pass
ac = WorksWith(a, c)
print(type(ac))
# 'WORKS_WITH'

1.2 子圖Subgraph對(duì)象

集合操作是創(chuàng)建子圖最簡(jiǎn)便的方法:

s = ab | ac
print(s)
# {(alice:Person {name:"Alice"}),  (bob:Person {name:"Bob"}),  (carol:Person {name:"Carol"}),  (Alice)-[:KNOWS]->(Bob),  (Alice)-[:WORKS_WITH]->(Carol)}
print(s.nodes())
# frozenset({(alice:Person {name:"Alice"}), (bob:Person {name:"Bob"}), (carol:Person {name:"Carol"})})
print(s.relationships())
# frozenset({(Alice)-[:KNOWS]->(Bob), (Alice)-[:WORKS_WITH]->(Carol)})

1.3 路徑Path對(duì)象和可遍歷Walkable類(lèi)型

可遍歷對(duì)象是添加了遍歷信息的子圖。

w = ab + Relationship(b, "LIKES", c) + ac
print(w)
# (Alice)-[:KNOWS]->(Bob)-[:LIKES]->(Carol)<-[:WORKS_WITH]-(Alice)

1.4 記錄Record對(duì)象

Record對(duì)象是值的有序有鍵的集合,和具名元組很像。

1.5 表格Table對(duì)象

Table對(duì)象是包含Record對(duì)象的列表。


2 圖數(shù)據(jù)庫(kù)

Graph對(duì)象是最重要的和Neo4j交互的類(lèi)。

from py2neo import Graph
graph = Graph(password="password")
print(graph.run("UNWIND range(1, 3) AS n RETURN n, n * n as n_sq").to_table())
#    n | n_sq
# -----|------
#    1 |    1
#    2 |    4
#    3 |    9

2.1 數(shù)據(jù)庫(kù)Database類(lèi)

用于連接圖數(shù)據(jù)庫(kù)

from py2neo import Database
db = Database("bolt://camelot.example.com:7687")

默認(rèn)值是bolt://localhost:7687

default_db = Database()
>>> default_db
<Database uri='bolt://localhost:7687'>

2.2 圖Graph

Graph類(lèi)表示Neo4j中的圖數(shù)據(jù)存儲(chǔ)空間。

>>> from py2neo import Graph
>>> graph_1 = Graph()
>>> graph_2 = Graph(host="localhost")
>>> graph_3 = Graph("bolt://localhost:7687")

match匹配:

for rel in graph.match((alice, ), r_type="FRIEND"):
    print(rel.end_node["name"])

merge融合:

>>> from py2neo import Graph, Node, Relationship
>>> g = Graph()
>>> a = Node("Person", name="Alice", age=33)
>>> b = Node("Person", name="Bob", age=44)
>>> KNOWS = Relationship.type("KNOWS")
>>> g.merge(KNOWS(a, b), "Person", "name")

再創(chuàng)建第三個(gè)節(jié)點(diǎn):

>>> c = Node("Company", name="ACME")
>>> c.__primarylabel__ = "Company"
>>> c.__primarykey__ = "name"
>>> WORKS_FOR = Relationship.type("WORKS_FOR")
>>> g.merge(WORKS_FOR(a, c) | WORKS_FOR(b, c))

nodes方法,找到所有符合條件的節(jié)點(diǎn):

>>> graph = Graph()
>>> graph.nodes[1234]
(_1234:Person {name: 'Alice'})
>>> graph.nodes.get(1234)
(_1234:Person {name: 'Alice'})
>>> graph.nodes.match("Person", name="Alice").first()
(_1234:Person {name: 'Alice'})

2.3 事務(wù)Transactions

commit() 提交事務(wù)

create(subgraph) 創(chuàng)建節(jié)點(diǎn)和關(guān)系

>>> from py2neo import Graph, Node, Relationship
>>> g = Graph()
>>> tx = g.begin()
>>> a = Node("Person", name="Alice")
>>> tx.create(a)
>>> b = Node("Person", name="Bob")
>>> ab = Relationship(a, "KNOWS", b)
>>> tx.create(ab)
>>> tx.commit()
>>> g.exists(ab)
True

2.4 查詢(xún)結(jié)果

Cursor類(lèi)

前進(jìn)一個(gè)節(jié)點(diǎn),打印節(jié)點(diǎn)的名字:

while cursor.forward():
    print(cursor.current["name"])

因?yàn)镃ursor是可迭代對(duì)象,也可以這樣:

for record in cursor:
    print(record["name"])

只關(guān)心一個(gè)節(jié)點(diǎn),則:

if cursor.forward():
    print(cursor.current["name"])

或:

print(next(cursor)["name"])

從單條記錄只返回一個(gè)值:

print(cursor.evaluate())

data(),提取出所有數(shù)據(jù):

>>> from py2neo import Graph
>>> graph = Graph()
>>> graph.run("MATCH (a:Person) RETURN a.name, a.born LIMIT 4").data()
[{'a.born': 1964, 'a.name': 'Keanu Reeves'},
 {'a.born': 1967, 'a.name': 'Carrie-Anne Moss'},
 {'a.born': 1961, 'a.name': 'Laurence Fishburne'},
 {'a.born': 1960, 'a.name': 'Hugo Weaving'}]

evaluate(field=0),從下條記錄返回第一個(gè)字段:

>>> from py2neo import Graph
>>> g = Graph()
>>> g.run("MATCH (a) WHERE a.email={x} RETURN a.name", x="bob@acme.com").evaluate()
'Bob Robertson'

stats(),返回查詢(xún)統(tǒng)計(jì):

>>> from py2neo import Graph
>>> g = Graph()
>>> g.run("CREATE (a:Person) SET a.name = 'Alice'").stats()
constraints_added: 0
constraints_removed: 0
contained_updates: True
indexes_added: 0
indexes_removed: 0
labels_added: 1
labels_removed: 0
nodes_created: 1
nodes_deleted: 0
properties_set: 1
relationships_created: 0
relationships_deleted: 0

to_data_frame(index=None, columns=None, dtype=None),將數(shù)據(jù)返回為pandas的DataFrame:

>>> from py2neo import Graph
>>> graph = Graph()
>>> graph.run("MATCH (a:Person) RETURN a.name, a.born LIMIT 4").to_data_frame()
   a.born              a.name
0    1964        Keanu Reeves
1    1967    Carrie-Anne Moss
2    1961  Laurence Fishburne
3    1960        Hugo Weaving

3 py2neo.matching – 實(shí)體匹配

3.1 節(jié)點(diǎn)匹配

使用NodeMatcher匹配節(jié)點(diǎn):

>>> from py2neo import Graph, NodeMatcher
>>> graph = Graph()
>>> matcher = NodeMatcher(graph)
>>> matcher.match("Person", name="Keanu Reeves").first()
(_224:Person {born:1964,name:"Keanu Reeves"})

使用where子句匹配:

>>> list(matcher.match("Person").where("_.name =~ 'K.*'"))
[(_57:Person {born: 1957, name: 'Kelly McGillis'}),
 (_80:Person {born: 1958, name: 'Kevin Bacon'}),
 (_83:Person {born: 1962, name: 'Kelly Preston'}),
 (_224:Person {born: 1964, name: 'Keanu Reeves'}),
 (_226:Person {born: 1966, name: 'Kiefer Sutherland'}),
 (_243:Person {born: 1957, name: 'Kevin Pollak'})]

排序order_by()和數(shù)量limit()限制:

>>> list(matcher.match("Person").where("_.name =~ 'K.*'").order_by("_.name").limit(3))
[(_224:Person {born: 1964, name: 'Keanu Reeves'}),
 (_57:Person {born: 1957, name: 'Kelly McGillis'}),
 (_83:Person {born: 1962, name: 'Kelly Preston'})]

只統(tǒng)計(jì)數(shù)量,用len():

>>> len(matcher.match("Person").where("_.name =~ 'K.*'"))
6

3.2 關(guān)系匹配RelationshipMatcher

使用的方法和節(jié)點(diǎn)匹配很相似:

first()

order_by(*fields)

where(*conditions, **properties)

4 對(duì)象圖映射Object-Graph Mapping

用于綁定Python對(duì)象和底層圖數(shù)據(jù)

class Movie(GraphObject):
    __primarykey__ = "title"

    title = Property()
    tag_line = Property("tagline")
    released = Property()

    actors = RelatedFrom("Person", "ACTED_IN")
    directors = RelatedFrom("Person", "DIRECTED")
    producers = RelatedFrom("Person", "PRODUCED")


class Person(GraphObject):
    __primarykey__ = "name"

    name = Property()
    born = Property()

    acted_in = RelatedTo(Movie)
    directed = RelatedTo(Movie)
    produced = RelatedTo(Movie)

4.1 圖對(duì)象

GraphObject,用作基類(lèi)

4.2 屬性Property()

>>> class Person(GraphObject):
...     name = Property()
...
>>> alice = Person()
>>> alice.name = "Alice Smith"
>>> alice.name
"Alice Smith"

4.3 標(biāo)簽Label()

標(biāo)簽是布爾值,默認(rèn)是False

>>> class Food(GraphObject):
...     hot = Label()
...
>>> pizza = Food()
>>> pizza.hot
False
>>> pizza.hot = True
>>> pizza.hot
True

4.4 關(guān)聯(lián)對(duì)象

class Person(GraphObject):
    __primarykey__ = "name"

    name = Property()

    likes = RelatedTo("Person")
for friend in person.likes:
    print(friend.name)

4.5 對(duì)象匹配

>>> Person.match(graph, "Keanu Reeves").first()
<Person name='Keanu Reeves'>
>>> list(Person.match(graph).where("_.name =~ 'K.*'"))
[<Person name='Keanu Reeves'>,
 <Person name='Kevin Bacon'>,
 <Person name='Kiefer Sutherland'>,
 <Person name='Kevin Pollak'>,
 <Person name='Kelly McGillis'>,
 <Person name='Kelly Preston'>]

4.6 對(duì)象操作

>>> alice = Person()
>>> alice.name = "Alice Smith"
>>> graph.push(alice)
>>> alice.__node__
(_123:Person {name: 'Alice Smith'})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,208評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,746評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,666評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,477評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,960評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,200評(píng)論 0 288
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,617評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,807評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,049評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,425評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,674評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,432評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,769評(píng)論 2 372