Neo4j 图数据库编程

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()
未经允许不得转载:一亩三分地 » Neo4j 图数据库编程