圖數據庫neo4j(二)python 連接neo4j

更多可以閱讀https://blog.csdn.net/column/details/23835.html

圖數據庫neo4j(二)python 連接neo4j

安裝所需連接驅動

pip install py2neo

這裏寫圖片描述
最開始安裝的是4.0,發現有很多問題,之後更換了V3版本

這裏寫圖片描述
這裏寫圖片描述

導入基本模塊

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

from py2neo import Graph,Node,Relationship

Node & Relationship

基本演示

下面通過Python來演示下Node & Relationship
Neo4j 裏面最重要的兩個數據結構就是節點和關係,即 Node 和 Relationship,可以通過 Node 或 Relationship 對象創建,實例如下:

from py2neo import Node, Relationship

a = Node('Person', name='Alice')
b = Node('Person', name='Bob')
r = Relationship(a, 'KNOWS', b)
print(a, b, r)

輸出結果:

(:Person {name: 'Alice'}) (:Person {name: 'Bob'}) (Alice)-[:KNOWS {}]->(Bob)

這樣我們就成功創建了兩個 Node 和兩個 Node 之間的 Relationship。

以dict形式傳參

Node 和 Relationship 都繼承了 PropertyDict 類,它可以賦值很多屬性,類似於Python字典的形式,例如可以通過如下方式對 Node 或 Relationship 進行屬性賦值,接着上面的代碼,實例如下:

a['age'] = 20
b['age'] = 21
r['time'] = '2017/08/31'
print(a, b, r)

注意:以上代碼必須在創建了node與relationship下進行添加dict形式纔有效。
運行結果:

(alice:Person {age:20,name:"Alice"}) (bob:Person {age:21,name:"Bob"}) (alice)-[:KNOWS {time:"2017/08/31"}]->(bob)

可見通過類似字典的操作方法就可以成功實現屬性賦值。

另外還可以通過 setdefault() 方法賦值默認屬性,例如:

a.setdefault('location', '北京')
print(a)

運行結果

(alice:Person {age:20,location:"北京",name:"Alice"})

可見沒有給 a 對象賦值 location 屬性,現在就會使用默認屬性。

但如果賦值了 location 屬性,則它會覆蓋默認屬性,例如:

a['location'] = '上海'
a.setdefault('location', '北京')
print(a)

運行結果:

(alice:Person {age:20,location:"上海",name:"Alice"})

update() 批量更新

另外也可以使用 update() 方法對屬性批量更新,接着上面的例子實例如下:

data = {
    'name': 'Amy',
    'age': 21
}
a.update(data)
print(a)

運行結果:

(alice:Person {age:21,location:"上海",name:"Amy"})

可以看到這裏更新了 a 對象的 name 和 age 屬性,沒有更新 location 屬性,則 name 和 age 屬性會更新,location 屬性則會保留。

Subgraph子圖

基本操作

Subgraph,子圖,是 Node 和 Relationship 的集合,最簡單的構造子圖的方式是通過關係運算符,實例如下:

from py2neo import Node, Relationship

a = Node('Person', name='Alice')
b = Node('Person', name='Bob')
r = Relationship(a, 'KNOWS', b)
s = a | b | r
print(s)

運行結果:

({(alice:Person {name:"Alice"}), (bob:Person {name:"Bob"})}, {(alice)-[:KNOWS]->(bob)})

這樣就組成了一個 Subgraph。

另外還可以通過 nodes() 和 relationships() 方法獲取所有的 Node 和 Relationship,實例如下:

print(s.nodes())
print(s.relationships())

運行結果:

frozenset({(alice:Person {name:"Alice"}), (bob:Person {name:"Bob"})})
frozenset({(alice)-[:KNOWS]->(bob)})

可以看到結果是 frozenset 類型。

Subgraph 的交集

另外還可以利用 & 取 Subgraph 的交集,例如:

s1 = a | b | r
s2 = a | b
print(s1 & s2)

運行結果:

({(alice:Person {name:"Alice"}), (bob:Person {name:"Bob"})}, {})

可以看到結果是二者的交集。

查詢基本屬性

另外我們還可以分別利用 keys()、labels()、nodes()、relationships()、types() 分別獲取 Subgraph 的 Key、Label、Node、Relationship、Relationship Type,實例如下:

s = a | b | r
print(s.keys())
print(s.labels())
print(s.nodes())
print(s.relationships())
print(s.types())

運行結果:

frozenset({'name'})
frozenset({'Person'})
frozenset({(alice:Person {name:"Alice"}), (bob:Person {name:"Bob"})})
frozenset({(alice)-[:KNOWS]->(bob)})
frozenset({'KNOWS'})

另外還可以用 order() 或 size() 方法來獲取 Subgraph 的 Node 數量和 Relationship 數量,實例如下:

from py2neo import Node, Relationship, size, order
s = a | b | r
print(order(s))
print(size(s))

運行結果:

2
1

Walkable–增加遍歷信息的 Subgraph

Walkable 是增加了遍歷信息的 Subgraph,我們通過 + 號便可以構建一個 Walkable 對象,例如:

from py2neo import Node, Relationship

a = Node('Person', name='Alice')
b = Node('Person', name='Bob')
c = Node('Person', name='Mike')
ab = Relationship(a, "KNOWS", b)
ac = Relationship(a, "KNOWS", c)
w = ab + Relationship(b, "LIKES", c) + ac
print(w)

運行結果:
(alice)-[:KNOWS]->(bob)-[:LIKES]->(mike)<-[:KNOWS]-(alice)
這樣我們就形成了一個 Walkable 對象。

另外我們可以調用 walk() 方法實現遍歷,實例如下:

from py2neo import walk

for item in walk(w):
    print(item)

運行結果:

(alice:Person {name:"Alice"})
(alice)-[:KNOWS]->(bob)
(bob:Person {name:"Bob"})
(bob)-[:LIKES]->(mike)
(mike:Person {name:"Mike"})
(alice)-[:KNOWS]->(mike)
(alice:Person {name:"Alice"})

可以看到它從 a 這個 Node 開始遍歷,然後到 b,再到 c,最後重新回到 a。

另外還可以利用 start_node()、end_node()、nodes()、relationships() 方法來獲取起始 Node、終止 Node、所有 Node 和 Relationship,例如:

print(w.start_node())
print(w.end_node())
print(w.nodes())
print(w.relationships())

運行結果:

(alice:Person {name:"Alice"})
(alice:Person {name:"Alice"})
((alice:Person {name:"Alice"}), (bob:Person {name:"Bob"}), (mike:Person {name:"Mike"}), (alice:Person {name:"Alice"}))
((alice)-[:KNOWS]->(bob), (bob)-[:LIKES]->(mike), (alice)-[:KNOWS]->(mike))

可以看到本例中起始和終止 Node 都是同一個,這和 walk() 方法得到的結果是一致的。

Graph

在 database 模塊中包含了和 Neo4j 數據交互的 API,最重要的當屬 Graph,它代表了 Neo4j 的圖數據庫,同時 Graph 也提供了許多方法來操作 Neo4j 數據庫。

Graph 在初始化的時候需要傳入連接的 URI,初始化參數有 bolt、secure、host、http_port、https_port、bolt_port、user、password,詳情說明可以參考:http://py2neo.org/v3/database.html#py2neo.database.Graph

初始化的實例如下:

from py2neo import Graph
graph_1 = Graph()
graph_2 = Graph(host="localhost")
graph_3 = Graph("http://localhost:7474/db/data/")

另外我們還可以利用 create() 方法傳入 Subgraph 對象來將關係圖添加到數據庫中,實例如下:

from py2neo import Node, Relationship, Graph

a = Node('Person', name='Alice')
b = Node('Person', name='Bob')
r = Relationship(a, 'KNOWS', b)
s = a | b | r
graph = Graph(password='123456')
graph.create(s)

另外還可以利用 data() 方法來獲取查詢結果:

from py2neo import Graph

graph = Graph(password='123456')
data = graph.data('MATCH (p:Person) return p')
print(data)

運行結果:

[{'p': (e0d0f96:Person {name:"Alice"})}, {'p': (cfe57d0:Person {name:"Bob"})}]

這裏是通過 CQL 語句實現的查詢,輸出結果即 CQL 語句的返回結果,是列表形式。

另外輸出結果還可以直接轉化爲 DataFrame 對象,實例如下:

from py2neo import Graph
from pandas import DataFrame
graph = Graph(password='123456')
data = graph.data('MATCH (p:Person) return p')
df = DataFrame(data)
print(df)

運行結果:

                 p
0  {'name': 'Alice'}
1    {'name': 'Bob'}

另外可以使用 find_one() 或 find() 方法進行 Node 的查找,可以利用 match() 或 match_one() 方法對 Relationship 進行查找:

from py2neo import Graph

graph = Graph(password='123456')
node = graph.find_one(label='Person')
print(node)
relationship = graph.match_one(rel_type='KNOWS')
print(relationship)

運行結果:

(c7402c7:Person {age:21,name:"Alice"})
(c7402c7)-[:KNOWS]->(e2c42fc)

如果想要更新 Node 的某個屬性可以使用 push() 方法,例如:

from py2neo import Graph, Node

graph = Graph(password='123456')
a = Node('Person', name='Alice')
node = graph.find_one(label='Person')
node['age'] = 21
graph.push(node)
print(graph.find_one(label='Person'))

運行結果:

(a90a763:Person {age:21,name:"Alice"})

如果想要刪除某個 Node 可以使用 delete() 方法,例如:

from py2neo import Graph

graph = Graph(password='123456')
node = graph.find_one(label='Person')
relationship = graph.match_one(rel_type='KNOWS')
graph.delete(relationship)
graph.delete(node)

在刪除 Node 時必須先刪除其對應的 Relationship,否則無法刪除 Node。

另外我們也可以通過 run() 方法直接執行 CQL 語句,例如:

from py2neo import Graph

graph = Graph(password='123456')
data = graph.run('MATCH (p:Person) RETURN p LIMIT 5')
print(list(data))

運行結果:

[('p': (b6f61ff:Person {age:20,name:"Alice"})), ('p': (cc238b1:Person {age:20,name:"Alice"})), ('p': (b09e672:Person {age:20,name:"Alice"}))]

NodeSelector
Graph 有時候用起來不太方便,比如如果要根據多個條件進行 Node 的查詢是做不到的,在這裏更方便的查詢方法是利用 NodeSelector,我們首先新建如下的 Node 和 Relationship,實例如下:

from py2neo import Graph, Node, Relationship

graph = Graph(password='123456')
a = Node('Person', name='Alice', age=21, location='廣州')
b = Node('Person', name='Bob', age=22, location='上海')
c = Node('Person', name='Mike', age=21, location='北京')
r1 = Relationship(a, 'KNOWS', b)
r2 = Relationship(b, 'KNOWS', c)
graph.create(a)
graph.create(r1)
graph.create(r2)

在這裏我們用 NodeSelector 來篩選 age 爲 21 的 Person Node,實例如下:

from py2neo import Graph, NodeSelector

graph = Graph(password='123456')
selector = NodeSelector(graph)
persons = selector.select('Person', age=21)
print(list(persons))

運行結果:

[(d195b2e:Person {age:21,location:"廣州",name:"Alice"}), (eefe475:Person {age:21,location:"北京",name:"Mike"})]

另外也可以使用 where() 進行更復雜的查詢,例如查找 name 是 A 開頭的 Person Node,實例如下:

from py2neo import Graph, NodeSelector

graph = Graph(password='123456')
selector = NodeSelector(graph)
persons = selector.select('Person').where('_.name =~ "A.*"')
print(list(persons))

運行結果:

[(bcd8072:Person {age:21,location:"廣州",name:"Alice"})]

在這裏用了正則表達式匹配查詢。

另外也可以使用 order_by() 進行排序:

f

rom py2neo import Graph, NodeSelector

graph = Graph(password='123456')
selector = NodeSelector(graph)
persons = selector.select('Person').order_by('_.age')
print(list(persons))

運行結果:

[(e3fc3d7:Person {age:21,location:"廣州",name:"Alice"}), (da0179d:Person {age:21,location:"北京",name:"Mike"}), (cafa16e:Person {age:22,location:"上海",name:"Bob"})]

前面返回的都是列表,如果要查詢單個節點的話,可以使用 first() 方法,實例如下:

from py2neo import Graph, NodeSelector

graph = Graph(password='123456')
selector = NodeSelector(graph)
person = selector.select('Person').where('_.name =~ "A.*"').first()
print(person)

運行結果:

(ea81c04:Person {age:21,location:"廣州",name:"Alice"})

更詳細的內容可以查看:http://py2neo.org/v3/database.html#cypher-utilities

OGM

OGM 類似於 ORM,意爲 Object Graph Mapping,這樣可以實現一個對象和 Node 的關聯,例如:

from py2neo.ogm import GraphObject, Property, RelatedTo, RelatedFrom


class Movie(GraphObject):
    __primarykey__ = 'title'

    title = Property()
    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')

我們可以用它來結合 Graph 查詢,例如:

from py2neo import Graph
from py2neo.ogm import GraphObject, Property

graph = Graph(password='123456')




class Person(GraphObject):
    __primarykey__ = 'name'

    name = Property()
    age = Property()
    location = Property()

person = Person.select(graph).where(age=21).first()
print(person)
print(person.name)
print(person.age)

運行結果:

<Person name='Alice'>
Alice
21

這樣我們就成功實現了對象和 Node 的映射。

我們可以用它動態改變 Node 的屬性,例如修改某個 Node 的 age 屬性,實例如下:

person = Person.select(graph).where(age=21).first()
print(person.__ogm__.node)
person.age = 22
print(person.__ogm__.node)
graph.push(person)

運行結果:

(ccf5640:Person {age:21,location:"北京",name:"Mike"})
(ccf5640:Person {age:22,location:"北京",name:"Mike"})

另外我們也可以通過映射關係進行 Relationship 的調整,例如通過 Relationship 添加一個關聯 Node,實例如下:

from py2neo import Graph
from py2neo.ogm import GraphObject, Property, RelatedTo

graph = Graph(password='123456')

class Person(GraphObject):
    __primarykey__ = 'name'

    name = Property()
    age = Property()
    location = Property()
    knows = RelatedTo('Person', 'KNOWS')

person = Person.select(graph).where(age=21).first()
print(list(person.knows))
new_person = Person()
new_person.name = 'Durant'
new_person.age = 28
person.knows.add(new_person)
print(list(person.knows))

運行結果:

[<Person name='Bob'>]
[<Person name='Bob'>, <Person name='Durant'>]

這樣我們就完成了 Node 和 Relationship 的添加,同時由於設置了 primarykey 爲 name,所以不會重複添加。

但是注意此時數據庫並沒有更新,只是對象更新了,如果要更新到數據庫中還需要調用 Graph 對象的 push() 或 pull() 方法,添加如下代碼即可:

graph.push(person)

也可以通過 remove() 方法移除某個關聯 Node,實例如下:

person = Person.select(graph).where(name='Alice').first()
target = Person.select(graph).where(name='Durant').first()
person.knows.remove(target)
graph.push(person)
graph.delete(target)

這裏 target 是 name 爲 Durant 的 Node,代碼運行完畢後即可刪除關聯 Relationship 和刪除 Node。

以上便是 OGM 的用法,查詢修改非常方便,推薦使用此方法進行 Node 和 Relationship 的修改。

更多內容可以查看:http://py2neo.org/v3/ogm.html#module-py2neo.ogm

案例:

from py2neo import Graph, Node, Relationship

    # 連接neo4j數據庫
    graph = Graph("http://127.0.0.1:7474";,username="neo4j",password="123456")
    # 創建結點:label結點,方便以後的結點查找操作
    temp_node1 = Node(lable="Person",name="node1")
    temp_node2 = Node(lable="Person",name="node2")
    graph.create(temp_node1)
    graph.create(temp_node2)
    # 建立關係
    node_1_call_node_2 = Relationship(temp_node1,'CALL',temp_node2)
    node_1_call_node_2['count'] = 1
    node_2_call_node_1 = Relationship(temp_node2,'CALL',temp_node1)
    graph.create(node_2_call_node_1)
    graph.create(node_1_call_node_2)
    # 更新關係或節點的屬性 push提交
    node_1_call_node_2['count']+=1
    graph.push(node_1_call_node_2)

    # 通過屬性值來查找節點和關係find_one
    find_code = graph.find_one(
    label="明教",
    property_key="name",
    property_value="張無忌"
    )
    print(find_code['name'])

    # find方法已被棄用:通過屬性值來查找所有節點和關係find替換爲:NodeSelector
    find = NodeSelector(graph).select('明教')
    for f in find:
        print(f['name'])
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章