Python使用py2neo操作图数据库neo4j的方法详解

Python使⽤py2neo操作图数据库neo4j的⽅法详解
本⽂实例讲述了Python使⽤py2neo操作图数据库neo4j的⽅法。分享给⼤家供⼤家参考,具体如下:
1、概念
图:数据结构中的图由节点和其之间的边组成。节点表⽰⼀个实体,边表⽰实体之间的联系。
图数据库:以图的结构存储管理数据的数据库。其中⼀些数据库将原⽣的图结构经过优化后直接存储,即原⽣图存储。还有⼀些图数据库将图数据序列化后保存到关系型或其他数据库中。
之所以使⽤图数据库存储数据是因为它在处理实体之间存在复杂关系的数据具有很⼤的优势。使⽤传统的关系型数据库在处理数据之间的关系时其实很不⽅便。例如查询选修⼀个课程的同学时需要join两个表,查询选修某个课程的同学还选修什么课程,这就需要两次join操作,当涉及到⼗分复杂的关系以及庞⼤的数据量时,关系型数据库效率⼗分低下。⽽通过图存储,可以通过节点之间的边⼗分便捷地查询到结果。
图模型:
节点(Node)是主要的数据元素,表⽰⼀个实体。
属性(Properties)⽤于描述实体的特征,以键值对的⽅式表⽰,其中键是字符串,可以对属性创建索引和约束。
关系(Relationships)表⽰实体之间的联系,关系具有⽅向,实体之间可以有多个关系,关系也可以具有属性
标签(Label)⽤于将实体分类,⼀个实体可以具有多个标签,对标签进⾏索引可以加速查
2、Neo4j
curl -O /neo4j-community-3.4.
tar -axvf neo4j-community-3.4.
修改配置⽂件f
# 修改第22⾏load csv时l路径,在前⾯加个#,可从任意路径读取⽂件
#dbms.directories.import=import
# 修改35⾏和36⾏,设置JVM初始堆内存和JVM最⼤堆内存
# ⽣产环境给的JVM最⼤堆内存越⼤越好,但是要⼩于机器的物理内存
# 修改46⾏,可以认为这个是缓存,如果机器配置⾼,这个越⼤越好
# 修改54⾏,去掉改⾏的#,可以远程通过ip访问neo4j数据库
# 默认 bolt端⼝是7687,http端⼝是7474,https关⼝是7473,不修改下⾯3项也可以
# 修改71⾏,去掉#,设置http端⼝为7687,端⼝可以⾃定义,只要不和其他端⼝冲突就⾏
#tor.bolt.listen_address=:7687
# 修改75⾏,去掉#,设置http端⼝为7474,端⼝可以⾃定义,只要不和其他端⼝冲突就⾏
# 修改79⾏,去掉#,设置http端⼝为7473,端⼝可以⾃定义,只要不和其他端⼝冲突就⾏
# 去掉#,允许从远程url来load csv
dbms.security.allow_csv_import_from_file_urls=true
# 修改250⾏,去掉#,设置neo4j-shell端⼝,端⼝可以⾃定义,只要不和其他端⼝冲突就⾏
dbms.shell.port=1337
# 修改254⾏,设置neo4j可读可写
3、py2neo
py2neo是⼀个社区第三⽅库,通过它可以更为便捷地使⽤python来操作neo4j
安装py2neo:pip install py2neo,我安装的版本是4.3.0
3.1、Node与Relationship
创建节点和它们之间的关系,注意在使⽤下⾯的py2neo相关类之前⾸先需要import导⼊:
# 引⼊库
from py2neo import Node, Relationship
# 创建节点a、b并定义其标签为Person,属性name
a = Node("Person", name="Alice",height=166)
b = Node("Person", name="Bob")
# 节点添加标签
a.add_label('Female')
# 创建ab之间的关系
ab = Relationship(a, "KNOWS", b)
# 输出节点之间的关系:(Alice)-[:KNOWS]->(Bob)
print(ab)
Node 和 Relationship 都继承了 PropertyDict 类,类似于python的dictionary,可以通过如下⽅式对 Node 或 Relationship 进⾏属性赋值和访问
# 节点和关系添加、修改属性
a['age']=20
ab['time']='2019/09/03'
# 删除属性
del a['age']
# 打印属性
print(a[name])
# 设置默认属性,如果没有赋值,使⽤默认值,否则设置的新值覆盖默认值
a.setdefault('sex','unknown')
# 更新属性
a.update(age=22, sex='female')
ab.update(time='2019/09/03')
3.2、Subgraph
由节点和关系组成的集合就是⼦图,通过关系运算符求交集&、并集|、差集-、对称差集^
subgraph.labels返回⼦图中所有标签集合,keys()返回所有属性集合,nodes返回所有节点集,relationships返回所有关系集# 构建⼀个⼦图
s = a | b | ab
# 对图中的所有节点集合进⾏遍历
for item des:
print('s的节点:', item)
通常将图中的所有节点和关系构成⼀个⼦图后再统⼀写⼊数据库,与多次写⼊单个节点相⽐效率更⾼
# 连接neo4j数据库,输⼊地址、⽤户名、密码
graph = Graph('localhost:7474', username='neo4j', password='123456')
# 将节点和关系通过关系运算符合并为⼀个⼦图,再写⼊数据库
s=a | b | ab
3.3、Walkable
walkable是在⼦图subgraph的基础上增加了遍历信息的对象,通过它可以便捷地遍历图数据库。
通过+号将关系连接起来就构成了⼀个walkable对象。通过walk()函数对其进⾏遍历,可以利⽤ start_node、end_node、nodes、relationships属性来获取起始 Node、终⽌ Node、所有 Node 和 Relationship
# 组合成⼀个walkable对象w
w = ab + bc + ac
# 对w进⾏遍历
for item in walk(w):
print(item)
# 访问w的初始、终⽌节点
print('起始节点:', w.start_node, ' 终⽌节点:', w.end_node)
# 访问w的所有节点、关系列表
print('节点列表:', w.nodes)
print('关系列表:', w.relationships)
运⾏结果为:
(:Person {age: 20, name: 'Bob'})
(Bob)-[:KNOWS {}]->(Alice)
(:Person {age: 21, name: 'Alice'})
(Alice)-[:LIKES {}]->(Mike)
(:Person {name: 'Mike'})
(Bob)-[:KNOWS {}]->(Mike)
(:Person {age: 20, name: 'Bob'})
起始节点: (:Person {age: 22, name: 'Bob', sex: 'female'})  终⽌节点: (:Person {age: 22, name: 'Bob', sex:
'female'})
节点列表: ((:Person {age: 22, name: 'Bob', sex: 'female'}), (:Person {age: 21, name: 'Alice'}), (:Person {name:
'Mike'}), (:Person {age: 22, name: 'Bob', sex: 'female'}))
关系列表: ((Bob)-[:KNOWS {time: '2019/09/03'}]->(Alice), (Alice)-[:LIKES {}]->(Mike), (Bob)-[:KNOWS {}]->(Mike))
3.4、Graph
py2neo通过graph对象操作neo4j数据库,⽬前的neo4j只⽀持⼀个数据库定义⼀张图
通过Graph的初始化函数完成对数据库的连接并创建⼀个graph对象
graph.delete()删除指定⼦图,graph.delete_all()删除所有⼦图
支撑梁graph.seperate()删除指定关系
# 初始化连接neo4j数据库,参数依次为url、⽤户名、密码
graph = Graph('localhost:7474', username='neo4j', password='123456')
# 写⼊⼦图w
# 删除⼦图w降压散
graph.delete(w)
# 删除所有图
graph.delete_all()
# 删除关系rel
graph.separate(rel)
graph.match(nodes=None, r_type=None, limit=None)查符合条件的关系,第⼀个参数为节点集合或者集合(起始节点,终⽌节点),如果省略代表所有节点。第⼆个参数为关系的属性,第三个为返回结果的数量。也可以使⽤match_one()代替,返回⼀条结果。例如查所有节点a认识的⼈:
# 查所有以a为起点,并且属性为KNOWS的关系
res = graph.match((a, ), r_type="KNOWS")
# 打印关系的终⽌节点,即为a所有认识的⼈
for rel in res:
d_node["name"])
使⽤des.match()查指定节点,可以使⽤first()、where()、order_by()等函数对查做⾼级限制
还可以通过节点或关系的id查
# 查标签为Person,属性name="Alice"的节点,并返回第⼀个结果
伸缩车棚
# 查所有标签为Person,name以B开头的节点,并将结果按照age字段排序
res = des.match("Person").where("_.name =~ 'B.*'").order_by('_.age')
for node in res:
print(node['name'])
# 查id为4的节点
t_node = des[4]
# 查id为196的关系
rel = lationships[196]
液压卸车翻板
通过Graph对象进⾏Cypher操作并处理返回结果
graph.evaluate()执⾏⼀个Cypher语句并返回结果的第⼀条数据
# 执⾏Cypher语句并返回结果集的第⼀条数据
选金工艺res = graph.evaluate('MATCH (p:Person) return p')
# 输出:(_3:Person {age: 20, name: 'Bob'})
print(res)
graph.run()执⾏Cypher语句并返回结果数据流的游标Cursor,通过forward()⽅法不断向前移动游标可以向前切换结果集的每条记录Record对象
# 查询(p1)-[k]->(p2),并返回所有节点和关系
gql="MATCH (p1:Person)-[k:KNOWS]->(p2:Person) RETURN *"
cursor=graph.run(gql)
# 循环向前移动游标
while cursor.forward():
# 获取并打印当前的结果集
record=cursor.current
print(record)
打印的每条Record记录对象如下所⽰,可以看到其中的元素是key=value的集合,通过⽅法get(key)可以取出具体元素。通过⽅法items(keys)可以将记录中指定的key按(key,value)元组的形式返回
<Record k=(xiaowang)-[:KNOWS {}]->(xiaozhang) p1=(_96:Person {name: 'xiaowang'}) p2=(_97:Person {name: 'xiaozhang'})>
record = cursor.current
print('通过get返回:', ('k'))
for (key, value) in record.items('p1', 'p2'):
print('通过items返回元组:', key, ':', value)
# 运⾏结果如下
'''
通过get返回: (xiaowang)-[:KNOWS {}]->(xiaozhang)
通过items返回元组: p1 : (_92:Person {name: 'xiaowang'})
通过items返回元组: p2 : (_93:Person {name: 'xiaozhang'})
'''
还可以将graph.run()返回的结果通过data()⽅法转化为字典列表,所有结果整体上是⼀个列表,其中每⼀条结果是字典的格式,其查询与结果如下,可以通过访问列表与字典的⽅式获取数据:
# 查询(p1)-[k]->(p2),并返回所有节点和关系
gql = "MATCH (p1:Person)-[k:KNOWS]->(p2:Person) RETURN *"
res = graph.run(gql).data()
print(res)
#结果如下:
'''
[{'k': (xiaowang)-[:KNOWS {}]->(xiaozhang),
'p1': (_196:Person {name: 'xiaowang'}),
'p2': (_197:Person {name: 'xiaozhang'})},
{'k': (xiaozhang)-[:KNOWS {}]->(xiaozhao),
'p1': (_197:Person {name: 'xiaozhang'}),
'p2': (_198:Person {name: 'xiaozhao'})},
{'k': (xiaozhao)-[:KNOWS {}]->(xiaoli),
'p1': (_198:Person {name: 'xiaozhao'}),
'p2': (_199:Person {name: 'xiaoli'})}
]
'''
通过graph.run().to_subgraph()⽅法将返回的结果转化为SubGraph对象,接着按之前操作SubGraph对象的⽅法取得节点对象,这⾥的节点对象Node可以直接按照之前的Node操作
# 查询(p1)-[k]->(p2),并返回所有节点和关系
gql = "MATCH (p1:Person)-[k:KNOWS]->(p2:Person) RETURN *"
sub_graph = graph.run(gql).to_subgraph()
# 获取⼦图中所有节点对象并打印
nodes=des
for node in nodes:
print(node)
# 输出的节点对象如下:
'''
(_101:Person {name: 'xiaozhang'})
(_100:Person {name: 'xiaowang'})
(_103:Person {name: 'xiaoli'})
119b(_102:Person {name: 'xiaozhao'})
'''
3.5、OGM
Object-Graph Mapping将图数据库中的节点映射为python对象,通过对象的⽅式对节点进⾏访问和操作。
将图中的每种标签定义为⼀个python类,其继承⾃GraphObject,注意使⽤前先import。在定义时可以指定数据类的主键,并定义类的属性Property()、标签Label()、关系RelatedTo()/RelatedFrom。
import GraphObject, Property, RelatedTo, RelatedFrom, Label
class Person(GraphObject):
# 定义主键
__primarykey__ = 'name'
# 定义类的属性
name=Property()
age=Property()
# 定义类的标签
student=Label()
# 定义Person指向的关系
knows=RelatedTo('Person','KNOWS')
# 定义指向Person的关系
known=RelatedFrom('Person','KNOWN')
通过类⽅法wrap()可以将⼀个普通节点转化为类的对象。
类⽅法match(graph,primary_key)可以在graph中查主键值为primary_key的节点
可以直接通过类构造⽅法创建⼀个对象,并直接访问对象的属性及⽅法,并通过关系⽅法add()添加关系
类的标签是⼀个bool值,默认为False,将其修改为True,即可为对象添加标签
# 将节点c转化为OGM类型
c=Person.wrap(c)
print(c.name)
# 查Person类中主键(name)为Alice的节点
ali=Person.match(graph,'Alice').first()
# 创建⼀个新的Person对象并对其属性赋值
new_person = Person()
new_person.name = 'Durant'
new_person.age = 28
# 标签值默认为False
print(new_person.student)
# 修改bool值为True,为对象添加student标签
new_person.student=True
# 将修改后的图写⼊数据库
graph.push(ali)
在定义节点类时还可以定义其相关的关系,例如通过RelatedTo()定义从该节点指出的关系,RelatedFrom()定义指向该节点的关系。通过对象调⽤关系的对应的⽅法完成节点周围的关系操作,例如add()添加关系,clear()清除节点所有的关系,get()获取关系属性,remove()清楚指定的关系,update()更新关系
class Person(GraphObject):
# 定义Person指向的关系
knows=RelatedTo('Person','KNOWS')
# 定义指向Person的关系
known=RelatedFrom('Person','KNOWN')
# 新建⼀个从ali指向new_person的关系
ali.knows.add(new_person)
# 清除ali节点所有的know关系
ali.knows.clear()
# 清除ali节点指向new_person的那个know关系
ve(new_person)
# 更新ali指向new_person关系的属性值
ali.knows.update(new_person,year=5)
# 获取ali指向new_person关系的属性year的值
(new_person,'year')
通过图对象也可以调⽤match⽅法对节点、关系进⾏匹配
# 获取第⼀个主键name名为Alice的Person对象
ali = Person.match(graph, 'Alice').first()
# 获取所有name以B开头的Person对象
Person.match(graph).where("_.name =~ 'B.*'")

本文发布于:2024-09-21 22:00:24,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/1/207415.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

下一篇:cbf190tr说明书
标签:关系   节点   数据库   属性   返回   对象
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议