这个库主要是配合neo4j图数据库来使用的python第三方库,最近在做图数据库,自然而然就需要py2neo库来对图数据库里的数据做处理,此篇文章主要是对py2neo的使用做一个简单的说明,虽然网上有很多相关的介绍文章,但是在使用的时候发现py2neo已经进入到了v4版本,很多文章还停留在v3版本,对v4版本的介绍比较少,并且在官网的handbook上介绍也只停留在函数介绍,并没有相关实例,因此这里将结合实际应用来谈使用。
官网handbook地址:https://py2neo.org/v4/
0x00 安装
这里安装很简单,直接pip即可
pip install py2neo
1
pipinstallpy2neo
我安装的时候由于没有挂代理,好多次都是下不下来所以导致失败,还有次失败是因为没有权限写入文件,su之后即可安装。。最可能出现的问题可能还是没挂代理导致网速过慢,某些包下载不下来导致报错。。
neo4j数据库这个直接下载官网上的desktop版本即可,使用上也是图形化界面,还是很方便的
这里使用上来说每个数据库新建的时候都要设置用户名和密码,这个在后面py2neo进行数据库连接的时候也用得到,因此需要好好记下来,然后点击start即可开启数据库,默认来说neo4j数据库提供了一个web接口(7474端口),desktop客户端也提供了浏览器,当然在firefox上也能登陆上
0x01 基本的使用说明
①数据库连接
from py2neo import *
graph = Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
1
2
frompy2neoimport *
graph=Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
这里的graph即为连接上的数据库,这里Graph第一个参数即为web的接口,username为用户名,password为密码,这里注意这个用户名和密码为新建project时设置的用户名密码,下面对数据库操作我们均可以用graph这个参数
②节点(Node)建立
在图数据库里组成部分其实很简单,节点(Node)、节点的属性(value)、关系(Relation),这也是图数据库最大的特点,举个简单的例子
Alice与Bob为朋友关系,Alice为20岁,Bob为25岁,这里Alice和Bob就是节点,关系为朋友,节点属性就是其对应的年龄,简化成三元组表示为(节点,关系,节点),不过需要注意的是在建立关系前我们需要先建立独立节点
from py2neo import *
graph = Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
node0 = Node('Person' , name = 'Alice')
node1 = Node('Person' , name = 'Bob')
node0['age'] = 20
node1['age'] = 25
graph.create(node0)
graph.create(node1)
1
2
3
4
5
6
7
8
9
10
11
frompy2neoimport *
graph=Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
node0=Node('Person',name='Alice')
node1=Node('Person',name='Bob')
node0['age']=20
node1['age']=25
graph.create(node0)
graph.create(node1)
这里首先连接数据库,然后我们利用Node()来创建节点,这里Person表示label,在图数据库中我们需要label来表示节点,在后面的图数据库搜索当中就是依靠这个label来进行搜寻的,因此这个label需要好好表示,后面的name其实已经表示这个节点的属性,这里再举一个例子,一本图书叫《飘》,那么建立节点
from py2neo import *
graph = Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
node = Node('Book' , name = 'Gone with the wind')
graph.create(node)
1
2
3
4
5
6
frompy2neoimport *
graph=Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
node=Node('Book',name='Gone with the wind')
graph.create(node)
由于节点属性为图书,因此这里label设置为Book。
回到上面的Alice与Bob,age这个表示节点的属性,与name同样表示为节点的属性,这里不再过多讲,最后就是节点的建立,这个也没什么好说的。。
③关系的建立
在上面我们已经建立了Alice和Bob的节点,但是在图数据库中这两个节点仍然是独立的
node0_know_node1 = Relationship(node0 , 'know' , node1)
graph.create(node0_know_node1)
1
2
node0_know_node1=Relationship(node0,'know',node1)
graph.create(node0_know_node1)
这里我们利用Relationship为他们两个建立了关系,关系属性为know
至此我们已经完成了三元组的关系,Alice -> Know -> Bob
完整的代码如下
from py2neo import *
graph = Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
node0 = Node('Person' , name = 'Alice')
node1 = Node('Person' , name = 'Bob')
node0['age'] = 20
node1['age'] = 25
node0_know_node1 = Relationship(node0 , 'know' , node1)
graph.create(node0)
graph.create(node1)
graph.create(node0_know_node1)
1
2
3
4
5
6
7
8
9
10
11
12
13
frompy2neoimport *
graph=Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
node0=Node('Person',name='Alice')
node1=Node('Person',name='Bob')
node0['age']=20
node1['age']=25
node0_know_node1=Relationship(node0,'know',node1)
graph.create(node0)
graph.create(node1)
graph.create(node0_know_node1)
0x02 进阶使用
我们现在已经知道如何存储数据了,但是这部分应该是在数据采集那块,也就是说我们对数据进行处理,然后将数据依照label和relation存储进数据库,在最后的页面展示时我们需要将数据从图数据库里拿出来,这时候就肯定会用到match,也就是数据库的检索功能
图的检索其实是有两种方式的,第一种就是依据节点label属性来搜索,第二种就是依据关系属性来检索。前一种就是说我现在要找所有的Person或者是Book,后一种就是说我要找互相认识的有哪些人,这里其实是依据Know这个关系来检索
①依据节点属性来检索
这个比较简单,前面建立节点时我们会给节点设置label,在这里就派上了大用场。
from py2neo import *
graph = Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
matcher = NodeMatcher(graph)
node = matcher.match('Person')
#print list(node)
1
2
3
4
5
6
7
frompy2neoimport *
graph=Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
matcher=NodeMatcher(graph)
node=matcher.match('Person')
#print list(node)
这里Nodematcher其实就是py2neo提供给我们的节点检索函数,下面就是依据Person这个label来进行检索,返回的是一个list列表,这个具体的应用可以看handbook,这里检索后面可以加where语句或者order by语句,,这个跟传统数据库大同小异
node = matcher.match('Person').first()
//返回列表的第一个节点
node = matcher.match('Person' , ‘name’ = 'Alice')
//返回列表中name为Alice的节点
node = matcher.match('Person' , ‘age’ = 20)
//返回列表中age为20的节点
node = matcher.match('Person').where("_.name = ~'A.*'")
//这里的where语句其实就是正则表达式了,返回列表中name属性以A开头的节点
1
2
3
4
5
6
7
8
9
10
node=matcher.match('Person').first()
//返回列表的第一个节点
node=matcher.match('Person',‘name’='Alice')
//返回列表中name为Alice的节点
node=matcher.match('Person',‘age’=20)
//返回列表中age为20的节点
node=matcher.match('Person').where("_.name = ~'A.*'")
//这里的where语句其实就是正则表达式了,返回列表中name属性以A开头的节点
基本的节点检索使用就在上面,如果更复杂的话也只能到官网上去看提供的函数了。。
②依据关系来检索
这里其实就是v4的一个特性,很多文章也没有介绍,官网上只给了个函数介绍,并没有如何使用,写下这篇文章也主要是为了记录这里!
这里先给个需求案例,来帮助说明使用
假如我们现在想知道Bob认识的人当中年龄在25岁以下的人的姓名,这里其实还可以扩展,比如加上性别,加上资产等等。。
从这个需求出发,第一步我们要做的就是做关系检索,匹配出Know关系的所有人,但是由于是三元组,也就是说在检索后返回的结果其实是(Bob,Know,Alice),因此我们对返回结果进行再次检索,检索Know两侧的姓名,如果一侧出现了Bob的名字,那么再根据另一侧,对其年龄进行查询,如果小于25则输出
我们回到handbook提供的使用说明
这里是handbook提供的使用说明,我上面的检索方法是依据第二个参数,也就是r_type参数来进行检索,这个参数主要是关系属性,但是我们可以看到其实是可以根据node节点来检索其关系及关系对应过去的节点,我们结合起来,那就是从Bob节点出发,然后设定关系为Know即可
这里为了最后的结果输出,又新加了一个节点为Jack,其age为50
matcher = RelationshipMatcher(graph)
result = matcher.match({node1},'know')
print list(result)
1
2
3
4
matcher=RelationshipMatcher(graph)
result=matcher.match({node1},'know')
printlist(result)
这里我们使用提供的RelationshuipMatcher函数来对节点及其关系进行检索
这里可以看到结果已经出来了,,可能有人说结果已经出来了,,直接对应过去找节点里的age值即可,但是这个返回结果没有提供任何查询节点的函数,我们只能够walk这个关系,简单点来说,就是无法直接提取Jack或者Alice这个节点的属性,不知道是我没找到还是官方api里真的没有。。
这里我采用的是walk函数,这也是官网handbook里提供的,主要对关系节点提供遍历查询
matcher = RelationshipMatcher(graph)
result = matcher.match({node1},'know')
for x in result:
for y in walk(x):
print y
print '-------'
1
2
3
4
5
6
7
matcher=RelationshipMatcher(graph)
result=matcher.match({node1},'know')
forxinresult:
foryinwalk(x):
printy
print'-------'
这里可以看到已经能够遍历节点了,那么直接提取节点的age值即可,小于25输出
完整代码如下:
from py2neo import *
if __name__ == '__main__':
graph = Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
graph.delete_all()
node0 = Node('Person' , name = 'Alice')
node1 = Node('Person' , name = 'Bob')
node2 = Node('Person' , name = 'Jack')
node0['age'] = 20
node1['age'] = 25
node2['age'] = 50
node0_know_node1 = Relationship(node1 , 'know' , node0)
node2_know_node1 = Relationship(node1 , 'know' , node2)
graph.create(node0)
graph.create(node1)
graph.create(node0_know_node1)
graph.create(node2_know_node1)
matcher = RelationshipMatcher(graph)
result = matcher.match({node1},'know')
for x in result:
for y in walk(x):
if type(y) is Node and y['age']<25:
print y['name']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
frompy2neoimport *
if__name__=='__main__':
graph=Graph("http://127.0.0.1:7474",username="neo4j",password="123456")
graph.delete_all()
node0=Node('Person',name='Alice')
node1=Node('Person',name='Bob')
node2=Node('Person',name='Jack')
node0['age']=20
node1['age']=25
node2['age']=50
node0_know_node1=Relationship(node1,'know',node0)
node2_know_node1=Relationship(node1,'know',node2)
graph.create(node0)
graph.create(node1)
graph.create(node0_know_node1)
graph.create(node2_know_node1)
matcher=RelationshipMatcher(graph)
result=matcher.match({node1},'know')
forxinresult:
foryinwalk(x):
iftype(y)isNodeandy['age']<25:
printy['name']
最终输出结果如下
其实最主要的就是这个walk函数,不过walk会将关系也会走一遍,这个由于节点是Node属性,关系是为know属性,对节点属性作一个判断即可~
上述如有不当之处,敬请指出~