py2neo 库提供了简便操作 Neo4j 数据库的接口。下面主要是对于结点、标签、属性、关系等操作的一些例子。
1. 结点操作
结点操作主要包括添加、删除、查询结点。添加新的结点可以使用 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()
程序最终执行结果是:
2. 属性操作
这里的属性操作主要是对结点属性进行添加、修改、删除操作。基本思路是先 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()
3. 标签操作
标签操作主要包含添加标签、删除标签。基本操作就是,先查询到相关的结点,然后使用 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()
程序最终执行结果:
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 # 连接图数据库 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()
5. 约束操作
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()