py2neo 库提供了简便操作 Neo4j 数据库的接口。下面主要是对于结点、标签、属性、关系等操作的一些例子。
- 结点操作 {#title-0} ==================
结点操作主要包括添加、删除、查询结点。添加新的结点可以使用 create、merge 两个方法,前者无论结点是否存在都会向数据库中添加结点,而后者则先判断结点是否存在,不存在则添加结点,如果存在则使用新结点替换旧结点。
查询结点主要使用 NodeMatcher 来完成。删除结点是先 MATCH 到满足条件的结点,然后使用 graph.delete(node) 来删除相关的结点。
from py2neo import Graph
from py2neo import Node
from py2neo import NodeMatcher
# 连接图数据库
graph = Graph('http://localhost:7474', auth=('neo4j', 'neo4j'))
# 删除所有结点
graph.delete_all()
# 1. 创建结点
def test01():
# 1.1 第一种方式
graph.run('create (p:Person{name:"周润发", age:65})')
# 1.2 第二种方式
graph.run('merge (p:Person{name:"张家辉", age:64})')
# 1.3 第三种方式
# 注意: Node 构建时,位置参数表示标签,关键字参数表示属性
node = Node('Person', 'Writer', name='刘德华', age=67)
graph.create(node)
# 1.4 第四种方式
# 由于在 Person 类别中,不存在 name 和 old_node 相同的结点
# 所以,此时执行 merge 为执行插入操作
old_node = Node('Person', name='史珍香', age=59)
graph.merge(old_node, 'Person', 'name')
# 由于在 Person 类别中,存在 name 和 new_node 相同的结点
# 所以,此时执行 merge 为执行替换操作
new_node = Node('Person', name='史珍香', age=59, sex='女')
graph.merge(new_node, 'Person', 'name')
# 2. 查询结点
def test02():
# 2.1 第一种方式
result = graph.run('match (p:Person) where p.age > 10 return p.name as name, p.age as age')
# name | age
# --------|-----
# 刘德华 | 67
# 周润发 | 65
print(result)
# result.data() 返回可迭代对象
# Name: 刘德华 Age: 67
# Name: 周润发 Age: 65
for node in result.data():
print('Name:', node['name'], 'Age:', node['age'])
# 2.2 第二种方式
result = NodeMatcher(graph).match('Person').where('_.age > 10').all()
# [Node('Person', 'Writer', age=67, name='刘德华'), Node('Person', age=65, name='周润发')]
print(result)
# Name:刘德华 Age:67 Label:['Person', 'Writer']
# Name:周润发 Age:65 Label:['Person']
for node in result:
print('Name:%s Age:%d Label:%s' % (node['name'], node['age'], list(node.labels)))
# 3. 删除结点
def test03():
# 新增几个结点
test_node1 = Node('Test', property1='value1', property2='value1')
test_node2 = Node('Test', property1='value2', property2='value2')
test_node3 = Node('Test', property1='value3', property2='value3')
# 新增几个结点
graph.create(test_node1)
graph.create(test_node2)
graph.create(test_node3)
# 删除结点
# 4.1 第一种方式
graph.run('match (n:Test{property1:"value2"}) delete n')
# 4.2 第二种方式
node = NodeMatcher(graph).match('Test').where(property1='value1').first()
graph.delete(node)
if __name__ == '__main__':
test01()
test02()
test03()
程序最终执行结果是:
- 属性操作 {#title-1} ==================
这里的属性操作主要是对结点属性进行添加、修改、删除操作。基本思路是先 MATCH 相关的结点,然后调用结点的 update({key: val...}) 来添加结点属性,使用 del 来删除结点属性,最后调用 graph.push(node) 将结点变化更新到数据库中。
from py2neo import Graph
from py2neo import Node
from py2neo import NodeMatcher
# 连接图数据库
graph = Graph('http://localhost:7474', auth=('neo4j', 'neo4j'))
# 删除所有结点
graph.delete_all()
# 1. 构建测试结点
def test01():
# 新增几个结点
test_node1 = Node('Test', property1='value1', property2='value1')
test_node2 = Node('Test', property1='value2', property2='value2')
test_node3 = Node('Test', property1='value3', property2='value3')
# 新增几个结点
graph.create(test_node1)
graph.create(test_node2)
graph.create(test_node3)
# 2. 修改属性
def test02():
# 2.1 第一种方式
graph.run('match (p:Test{property1:"value1"}) set p.property1="new_value1", p.property2="new_value1"')
# 2.2 第二种方式
# 从数据库中查询出 Node, 会有 identity 属性, 表示和数据库关联
node = NodeMatcher(graph).match('Test').where(property1='value3').first()
# 7
print(node.identity)
# (_7:Test {property1: 'value3', property2: 'value3'})
print(node)
node.update({'property1': 'new_value3', 'property2': 'new_value3'})
# (_7:Test {property1: 'new_value3', property2: 'new_value3'})
print(node)
# push 将修改后的结点更新到数据库
graph.push(node)
# 3. 添加属性
def test03():
# 3.1 第一种方式
graph.run('match (p:Test{property1:"value2"}) set p.property3="value2", p.property4="value2"')
# 3.2 第二种方式
node = NodeMatcher(graph).match('Test').where(property1='value2').first()
node.update({'property5': 'value2'})
graph.push(node)
# 4. 删除属性
def test04():
# 4.1 第一种方式
graph.run('match (p:Test{property1:"value2"}) remove p.property1, p.property2')
# 4.2 第二种方式
node = NodeMatcher(graph).match('Test').where(property3='value2').first()
del node['property4']
graph.push(node)
if __name__ == '__main__':
test01()
test02()
test03()
test04()
- 标签操作 {#title-2} ==================
标签操作主要包含添加标签、删除标签。基本操作就是,先查询到相关的结点,然后使用 add_label、update_labels、remove_label、clear_labels 来添加和删除结点,最后要调用 graph.push(node) 来将结点的变化更新到数据库中。
from py2neo import Graph
from py2neo import Node
from py2neo import NodeMatcher
graph = Graph('http://localhost:7474', auth=('neo4j', 'neo4j'))
graph.delete_all()
# 1. 构建测试结点
def test01():
# 新增几个结点
test_node1 = Node('Test1', p1='value1')
test_node2 = Node('Test1', p1='value2')
test_node3 = Node('Test1', p1='value3')
# 新增几个结点
graph.create(test_node1)
graph.create(test_node2)
graph.create(test_node3)
# 打印所有标签
print('所有结点标签:', list(graph.schema.node_labels))
# 2. 添加标签
def test02():
# 2.1 第一种方式
graph.run('match (n:Test1) set n:Test2')
# 2.2 第二种方式
nodes = NodeMatcher(graph).match('Test1').all()
for node in nodes:
# 一次添加一个标签
node.add_label('Test3')
# 一次添加多个标签
node.update_labels(['Test4', 'Test5'])
# 结点更新到数据库
graph.push(node)
# 3. 删除标签
def test03():
# 3.1 第一种方式
graph.run('match (n:Test1) remove n:Test2:Test3')
# 3.2 第二种方式
nodes = NodeMatcher(graph).match('Test1').all()
for node in nodes:
# 一次删除一个标签
node.remove_label('Test4')
# 删除结点所有标签
# node.clear_labels()
# 结点更新到数据库
graph.push(node)
if __name__ == '__main__':
test01()
test02()
test03()
程序最终执行结果:
- 关系操作 {#title-3} ==================
from py2neo import Graph
from py2neo import Node
from py2neo import NodeMatcher
from py2neo import Relationship
from py2neo import Subgraph
from py2neo import RelationshipMatcher
# 连接图数据库
graph = Graph('http://localhost:7474', auth=('neo4j', 'neo4j'))
# 删除所有结点
graph.delete_all()
# 1. 构建测试结点
def test01():
nodes = []
for index in range(6):
node = Node('Person', name=f'name{index}')
nodes.append(node)
# 先构建子图,批量添加结点
graph.create(Subgraph(nodes))
# 2. 添加结点关系
def test02():
# 2.1 第一种方式
graph.run('match (p1:Person{name:"name0"}), (p2:Person{name:"name1"}) merge (p1)-[:RELATION8]->(p2)')
# 2.2 第二种方式
node1 = NodeMatcher(graph).match('Person').where(name='name1').first()
node2 = NodeMatcher(graph).match('Person').where(name='name2').first()
graph.create(Relationship(node1, 'RELATION8', node2, att='rel2'))
# 2.3 第三种方式
names = [f'name{index + 2}' for index in range(4)]
relations = []
for index in range(len(names) - 1):
name1, name2 = names[index], names[index + 1]
relation_type = f'RELATION{index + 2}'
node1 = NodeMatcher(graph).match('Person').where(name=name1).first()
node2 = NodeMatcher(graph).match('Person').where(name=name2).first()
relations.append(Relationship(node1, relation_type, node2))
# 先添加结点,再构建结点关系
sub_graph = Subgraph(relationships=relations)
graph.create(sub_graph)
# 3. 删除结点关系
def test03():
# 3.1 第一种方式
graph.run('match (:Person{name:"name2"})-[r]->(:Person{name:"name3"}) delete r')
# 3.2 第二种方式
node4 = NodeMatcher(graph).match('Person').where(name='name4').first()
node5 = NodeMatcher(graph).match('Person').where(name='name5').first()
relation = RelationshipMatcher(graph).match({node4, node5}).first()
# 删除结点和关系
# graph.delete(relation)
# 只删除结点关系
graph.separate(relation)
# 4. 查询结点关系
def test04():
# 4.1 获得所有关系类型
relation_types = list(graph.schema.relationship_types)
print('所有关系类型:', relation_types)
# 4.2 遍历具有某种关系的两个结点
for relation_type in relation_types:
relations = RelationshipMatcher(graph).match(r_type=relation_type).all()
for relation in relations:
print(relation_type, relation.start_node, relation.end_node)
# 4.3 查询任意两个结点之间的关系
node1 = NodeMatcher(graph).match('Person', name='name1').first()
node2 = NodeMatcher(graph).match('Person', name='name2').first()
relation = RelationshipMatcher(graph).match([node1, node2]).first()
# 打印关系名称,开始和结束结点,关系的属性名和属性值
print(type(relation).__name__, relation.start_node, relation.end_node, relation.keys(), relation.values())
if __name__ == '__main__':
test01()
test02()
test03()
test04()
- 约束操作 {#title-4} ==================
from py2neo import Graph
from py2neo import Node
from py2neo import NodeMatcher
from py2neo import Relationship
from py2neo import Subgraph
from py2neo import RelationshipMatcher
import py2neo
# 连接图数据库
graph = Graph('http://localhost:7474', auth=('neo4j', 'neo4j'))
# 删除所有结点
graph.delete_all()
def test():
try:
# 设置 Person 标签的 name 属性唯一
graph.schema.create_uniqueness_constraint('Person', 'name')
# 创建索引
# graph.schema.create_index()
except py2neo.database.work.ClientError:
# 删除唯一约束
# graph.schema.drop_uniqueness_constraint('Person', 'name')
print('唯一约束')
node1 = Node('Person', name='name1')
node2 = Node('Person', name='name2')
node3 = Node('Person', name='name1')
graph.create(node1)
graph.create(node2)
# 报异常
graph.create(node3)
if __name__ == '__main__':
test()