Press "Enter" to skip to content

Pyhton操作Neo4j图数据库实践(南北朝隋唐历史北朝主要人物知识图谱)

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

独孤信“第一岳父”之称很形象,他有三个女儿做了三个朝代皇后,以及杨坚、杨广、李渊等人关系。本文试着使用图数据库(neo4j)表达这段南北朝隋唐历史北朝主要人物知识图谱。

1. Neo4j与py2neo

 

neo4j目前是图数据库的主流,neo4j的Cypher语法简单直观,但是不便于流程化。如果习惯在python环境下处理数据,那幺还是要用到python的neo4j库,即py2neo.

 

py2neo本身并不复杂,但要先适应它的思考模式。另一个问题是py2neo文档的示例较少,而且不同版本的py2neo挺不相同,容易弄混。本文基于Neo4j3.5.x及py2neo 2021.2.3。

 

创建neo4j图数据库有常用数据库接口(py2neo )和数据库语言(Cypher)两种方法,本文重点采用python程序py2neo 方法。

 

安装Pyhton操作Neo4j图数据库驱动接口

 

pip install py2neo

 

第一步:连接图数据库。

 

from py2neo import Graph,Node,Relationship
##连接neo4j数据库,输入地址、用户名、密码
graph = Graph('http://192.168.19.229:7474/',auth=('neo4j','1526') ) #username='neo4j',password='1526')
graph

 

Graph('http://192.168.19.229:7474')

 

2. 创建实体与关系

 

2.1. 创建节点Node

 

##创建结点
# 如果使用lable='',则是表示Property Keys
#person_node_1 = Node(label='person',name='李渊',dynasty=['隋朝','唐朝'],post=['唐高祖']) 
person_node_1 = Node('person',name='李渊',dynasty=['隋朝','唐朝'],post='唐高祖') 
person_node_2 = Node('person',name='李世民',dynasty=['隋朝','唐朝'],post='唐太宗')
person_node_3 = Node('person',name='独孤曼陀',dynasty=['隋朝','北周'],post='元贞皇后')
person_node_4 = Node('person',name='杨广',dynasty='隋朝',post='隋炀帝')
person_node_5 = Node('person',name='杨坚',dynasty=['隋朝','北周'],post='隋文帝')
person_node_6 = Node('person',name='独孤伽罗',dynasty=['隋朝','北周'],post='文献皇后')
person_node_7 = Node('person',name='独孤信',dynasty=['西魏','北周'],post='柱国大将军')
person_node_8 = Node('person',name='萧皇后',dynasty=['梁朝','隋朝','唐朝'],post='皇后')
person_node_9 = Node('person',name='独孤皇后',dynasty='北周',post='独孤皇后')
person_node_10 = Node('person',name='宇文毓',dynasty='北周',post='周明帝')

 

2.2. 创建关系Relationship

 

R_12 = Relationship(person_node_1, '父子', person_node_2)
R_31 = Relationship(person_node_3, '母子', person_node_1)
R_36 = Relationship(person_node_3, '姊妹', person_node_6)
R_64 = Relationship(person_node_6, '母子', person_node_4)
R_56 = Relationship(person_node_5, '夫妻', person_node_6)
R_76 = Relationship(person_node_7, '父女', person_node_6)
R_73 = Relationship(person_node_7, '父女', person_node_3)
R_54 = Relationship(person_node_5, '父子', person_node_4)
R_48 = Relationship(person_node_4, '夫妻', person_node_8)
R_79 = Relationship(person_node_7, '父女', person_node_9)
R_90 = Relationship(person_node_10, '夫妻', person_node_9)

 

注,有新的写法,源代码中给出:

 

The positional arguments passed to the constructor identify the nodes to

 

relate and the type of the relationship. Keyword arguments describe the

 

properties of the relationship::

 

>>> from py2neo import Node, Relationship
   >>> a = Node("Person", name="Alice")
   >>> b = Node("Person", name="Bob")
   >>> a_knows_b = Relationship(a, "KNOWS", b, since=1999)

 

This class may be extended to allow relationship types names to be

 

derived from the class name. For example::

 

>>> WORKS_WITH = Relationship.type("WORKS_WITH")
   >>> a_works_with_b = WORKS_WITH(a, b)
   >>> a_works_with_b
   (Alice)-[:WORKS_WITH {}]->(Bob)

 

2.3. 按事务管理,写入/删除数据

 

2.3.1. 写入/创建

 

# 事务开始
tx = graph.begin()
# 创建节点
tx.create(person_node_1)
tx.create(person_node_2)
tx.create(person_node_4)
tx.create(person_node_5)
tx.create(person_node_6)
tx.create(person_node_3)
tx.create(person_node_7)
tx.create(person_node_8)
tx.create(person_node_9)
tx.create(person_node_10)
# 创建关系
tx.create(R_12)
tx.create(R_31)
tx.create(R_36)
tx.create(R_64)
tx.create(R_56)
tx.create(R_76)
tx.create(R_73)
tx.create(R_54)
tx.create(R_48)
tx.create(R_79)
tx.create(R_90)
# (事务)提交数据
graph.commit(tx)

 

2.3.2. 删除

 

# 删除节点
#graph.delete(person_node_1)
#graph.delete(person_node_2)

 

如果使用delete删除关系,则将相关的节点也删除。

 

3. 增删节点与关系

 

对于增删操作,与传统数据库一样,最好先判断节点、关系是否存在,本文暂时不具体展开介绍。

 

3.1. 查询节点补充建立关系

 

# 增补节点和关系
person_node_18 = Node('person',name='宇文阐',dynasty='北周',post='周静帝')
# nodes = NodeMatcher(graph)
# 增补关系,先把节点查询出来
node_p1 = graph.nodes.match('person',name='宇文泰').first()
node_p2 = graph.nodes.match('person',name='宇文毓').first()
node_p3 = graph.nodes.match('person',name='宇文赟').first()
node_p3

 

Node('person', dynasty='北周', name='宇文赟', post='北周宣帝')

 

node_d = graph.nodes.match('dynasty',name='北周').first()
node_d

 

Node('dynasty', name='北周', region='北朝')

 

R_1 = Relationship(node_p1, '父子', node_p2)
R_2 = Relationship(node_p3, '父子', person_node_18)
RDP_1 = Relationship(person_node_18, '亡国',node_d )

 

tx = graph.begin()
tx.create(person_node_18)
tx.create(R_1)
tx.create(R_2)
tx.create(RDP_1)
graph.commit(tx)

 

打开浏览器,http://localhost:7474/browser/,将给出如下的图。

这张图有点问题,宇文泰是西魏权臣掌控者,在其去世后,由其侄子宇文护扶持其子宇文觉建立了北周,修改一下。

 

3.2. 删除错误的关系并修改

 

删除宇文泰与北周的关系,新建立与西魏的关系。其中,删除关系是指解除分离的含义,使用separate()断开关系。

 

#查找北周的臣民
node_d = graph.nodes.match('dynasty',name='北周').first()
node_p1 = graph.nodes.match('person',name='宇文泰').first()
relation_1 = graph.match_one((node_d,node_p1),r_type='国人')
print(relation_1)
#graph.delete(relation_1) #将删除关系及相关的节点(node)
graph.separate(relation_1)

 

(北周)-[:国人 {}]->(宇文泰)

 

#补充关系
node_p1 = graph.nodes.match('person',name='宇文泰').first()
node_d1 = graph.nodes.match('dynasty',name='西魏').first()
node_p2 = graph.nodes.match('person',name='独孤信').first()
RDP_1 = Relationship(node_d1, '国人', node_p1)
RDP_2 = Relationship(node_d1, '国人', node_p2)
tx = graph.begin()
tx.create(RDP_1)
tx.create(RDP_2)
graph.commit(tx)

 

修改后的效果图如下所示,还是有些问题,欢迎读者补充完善。

 

 

4. 关于基本常用查询

 

4.1. 节点node查询

 

node_d = graph.nodes.match('dynasty')
for rel in node_d:
    print(rel['name'],rel['region'])

 

西魏 北朝
梁朝 南朝
隋朝 中国
唐朝 中国
北周 北朝
陈朝 南朝

 

node_d = graph.nodes.match('dynasty').where("_.region='北朝'")
for rel in node_d:
    print(rel['name'],rel['region'])

 

西魏 北朝
北周 北朝

 

4.2. 关系Relationship查询

 

#查询关系是’国人‘的所有关系(relationship)
relation_1 = graph.match_one(r_type='国人')
relation_1

 

国人(Node('person', dynasty='陈朝', name='广德公主', post='隋炀帝嫔妃'), Node('dynasty', name='陈朝', region='南朝'))

 

#查找北周的臣民,match(nodes=None,r_type,**properties)
#node顺序为:开始节点,结束节点(可省略结束节点)
node_d = graph.nodes.match('dynasty',name='北周').first()
relation_1 = graph.match((node_d,),r_type='国人')
for rel in relation_1:
    print(rel)
    print(rel.start_node['name'], rel.end_node['name'], rel.end_node['post'])
relation_3 = graph.match_one((node_d,),r_type='国人')
print(relation_3)
node_p1

 

(北周)-[:国人 {}]->(宇文邕)
北周 宇文邕 北周武帝
(北周)-[:国人 {}]->(宇文泰)
北周 宇文泰 太师
(北周)-[:国人 {}]->(宇文赟)
北周 宇文赟 北周宣帝
(北周)-[:国人 {}]->(宇文毓)
北周 宇文毓 周明帝
(北周)-[:国人 {}]->(独孤皇后)
北周 独孤皇后 独孤皇后
(北周)-[:国人 {}]->(独孤伽罗)
北周 独孤伽罗 文献皇后
(北周)-[:国人 {}]->(独孤曼陀)
北周 独孤曼陀 元贞皇后
(北周)-[:国人 {}]->(独孤信)
北周 独孤信 柱国大将军
(北周)-[:国人 {}]->(宇文邕)
Node('person', dynasty='西魏', name='宇文泰', post='太师')

 

5. 补充数据库语言(Cypher)常用语句

删除所有内容,清空数据库:

MATCH (n)

 

DETACH DELETE n

删除所有person节点,自动删除关系:

MATCH (n:person)

 

DETACH DELETE n

删除person和dynasty多种节点:

MATCH (n:person),(m:dynasty)

 

DETACH DELETE n,m

查询多节点:

MATCH (n:dynasty),(m:person) RETURN n,m

提高查询速度,创建索引:

CREATE INDEX ON :person(name)

 

6. 小结

 

在中国的历史长河之中,历史人物及其典故众多,基于图数据库的知识图谱将为我们学习、掌握历史提供新思维,便于整理掌握。

 

关于知识图谱的使用,后续将逐步展开学习,欢迎一起研究。

 

参考:

 

肖永威. Neo4j图数据库入门实践 . CSDN博客, 2021.10

 

The Py2neo Handbook , 2021.1

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注