1. neo4j数据类型

1.Node: 节点, 基本语法:Node(label, *properties)

第一步:连接neo4j数据库

1
2
3
4
from py2neo import *

url = "http://localhost:7474"
graph = Graph(url, username="neo4j", password="szyh")

第二步:创建节点:

1
2
3
4
5
6
7
8
9
10
# 建立节点
node_1 = Node("英雄", name="张无忌")
node_2 = Node("英雄", name="杨道", 武力值='100')
node_3 = Node("派别", name="明教")

# 存入图数据库
graph.create(node_1)
graph.create(node_2)
graph.create(node_3)
print(node_1)

image

2 relationship关系基本语法: Relationship((start_node, type, end_node, **properties)

1
2
3
4
5
6
7
# 添加关系
node_1_to_node_2 = Relationship(node_1, '教主', node_2)
node_3_to_node_1 = Relationship(node_3, '统领', node_1)
node_2_to_node_3 = Relationship(node_2, '师出', node_3)
graph.create(node_1_to_node_2)
graph.create(node_3_to_node_1)
graph.create(node_2_to_node_3)

image

  1. Path路径,基本语法:Path(*entities), 注意entities是实体(关系,节点都可以作为实体)

image

  1. Subgraph:子图是节点和关系的任意集合,它也是Node, Relationship和Path的基类, 基本语法:Subgraph(nodes, relationships)。 空子图表示为None, 使用bool()可以测试是否为空,参数要按数组输入,如下面代码:
1
2
3
4
5
6
7
8
9
10
11
# 创建子图,通过子图的方式更新数据库
node_7 = Node('英雄', name='张翠山')
node_8 = Node('英雄', name='殷素素')
node_9 = Node('英雄', name='狮王')

relationship7 = Relationship(node_1, '生父', node_7)
relationship8 = Relationship(node_1, '生母', node_8)
relationship9 = Relationship(node_1, '义父', node_9)
subgraph_1 = Subgraph(nodes=[node_7, node_8, node_9],
relationships=[relationship7, relationship8, relationship9])
graph.create(subgraph_1)

image

工作流

  1. GraphService: 基于图服务的工作流
  2. Graph: 基于图数据库的工作流
  3. Transaction: 基于事务的工作流,一个Transaction分两个任务,增加一个新节点,将该节点与已有节点创建新关系。这两个任务有一个没完成,整个工作流就不会生效。通常,这种方式通过Graph.begin(readonly=False)构造函数构造,参数readonly表示只读
1
2
3
4
5
6
7
8
9
10
11
# 创建一个新事务
transcation_1 = graph.begin()
# 创建一个新Node
node_10 = Node('武当', name='张三丰')
transcation_1.create(node_10)
# 创建两个关系: 张无忌->(师公)->张三丰 张翠山->(妻子)->殷素素
relationship10 = Relationship(node_1, '师公', node_10)
relationship11 = Relationship(node_7, '妻子', node_8)
transcation_1.create(relationship10)
transcation_1.create(relationship11)
transcation_1.commit()

一个transaction增加的一个节点和两个关系

image

  1. 删除数据库中所有的节点和关系: graph.delete_all()
  2. 其他删除方法如下(删除的基础是查询,但凡查询条件没错,就不会删错)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 删除所有,
# graph.delete_all()

# 按照id删除,要删除节点前,首先需删除关系,否则会报错:ClientError
# graph.run('math (r) where id(r) = 3 delete r')
# 按照name属性删除,先增加一个独立的节点
node_x = Node('英雄', name='韦一笑')
# graph.create(node_x)

# graph.run('match (n:英雄{name:\'韦一笑\'}) delete n')

# 删除一个节点及与之相连的关系
# graph.run('match (n:英雄{name:\'韦一笑\'}) detach delete n')
# 删除某一类型的关系
graph.run('match ()-[r:喜欢]->() delete r;')
# 删除子图
# delete(subgraph_1)

1
2
3
4
5
# 改
# 将狮王的武力值改为100
node_9['武力值']=100
# 本地修改完,要push到服务器上哦
test_graph.push(node_9)

查询

查询,按照路径、节点、关系等查询

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
# 为了方便查询更多内容,新增一些关系和节点
transcation_2 = graph.begin()
node_100 = Node('巾帼', name='赵敏')
re_100 = Relationship(node_1, 'Love', node_100)

node_101 = Node('巾帼', name='周芷若')
re_101 = Relationship(node_1, 'knows', node_101)
re_101_ = Relationship(node_101, 'hate', node_100)

node_102 = Node('巾帼', name='小昭')
re_102 = Relationship(node_1, 'knows', node_102)

node_103 = Node('巾帼', name='蛛儿')
re_103 = Relationship(node_103, 'Love', node_1)
transcation_2.create(node_100)
transcation_2.create(re_100)

transcation_2.create(node_101)
transcation_2.create(re_101)
transcation_2.create(re_101_)

transcation_2.create(node_102)
transcation_2.create(re_102)

transcation_2.create(node_103)
transcation_2.create(re_103)
transcation_2.commit()

image

NodeMatcher: 定位满足特定条件的节点,基本语法:NodeMatcher(graph).match(labels, *properties),

方法名 功能
first() 返回查询结果第一个Node, 没有则返回空
where(conditino,properties) 过滤查询结果
order_by 排序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 定义查询
node_match = NodeMatcher(graph)
# # 单个节点, 按照label和name查询
node_single = node_match.match('英雄', name='杨逍').first()
print("单节点查询:", node_single)

# # 按label查询
# node_hero = list(node_match.match('英雄').all())
# print("查询结果类型", type(node_hero))
node_hero = node_match.match('英雄').__iter__()

# 循环取值
i = 0
for node in node_hero:
print("label查询第{}个为{}".format(i, node))
i += 1

# 按照name查询
node_name = node_match.match(name='张无忌')
print("name查询结果", node_name)

# 按照id查询
node_id = node_match.get(1)
print("id查询结果", node_id)
  1. NodeMatch, 基本用法, NodeMatch(graph, labels=frozenset({}), predicates=(), order_by=(), skip=None, limit=None)可以看出,NodeMatcher与NodeMatch参数完全不同,后面可以加很多条件
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
node_match1 = NodeMatch(graph, labels=frozenset({'英雄'}))
print('='*15,'遍历所有节点', '='*15)
for node in iter(node_match1):
print(node)
print('='*15,'查询结果计数', '='*15)
print(node_match1.__len__())

# 按照武力值排序查询结果
print('='*15,'按照武力值排序查询结果', '='*15)
wu = node_match1.order_by('_.武力值')
for i in wu:
print(i)
=============== 遍历所有节点 ===============
(_3104:英雄 {name: '\u6768\u9053', 武力值: '100'})
(_3257:英雄 {name: '\u5f20\u65e0\u5fcc'})
(_4209:英雄 {name: '\u5f20\u7fe0\u5c71'})
(_4210:英雄 {name: '\u72ee\u738b', 武力值: 10})
(_4211:英雄 {name: '\u6bb7\u7d20\u7d20'})
=============== 查询结果计数 ===============
5
=============== 按照武力值排序查询结果 ===============
(_3104:英雄 {name: '\u6768\u9053', 武力值: '100'})
(_4210:英雄 {name: '\u72ee\u738b', 武力值: 10})
(_3257:英雄 {name: '\u5f20\u65e0\u5fcc'})
(_4209:英雄 {name: '\u5f20\u7fe0\u5c71'})
(_4211:英雄 {name: '\u6bb7\u7d20\u7d20'})
  1. RelationshipMatcher:用于选择满足一组特定标准的关系的匹配器,基础语法,relation=RelationshipMatcher(graph)
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
relation = RelationshipMatcher(graph)
# Node表示any node
print('='*15,'hate关系查询', '='*15)
x = relation.match(nodes=None, r_type='hate')
for x_ in x:
print(x_)

# 增加两关系
rel_1 = Relationship(node_101, '情敌', node_102)
rel_2 = Relationship(node_102, '情敌', node_103)
graph.create(rel_1)
graph.create(rel_2)

# 情敌查询结果
print('='*15,'hate关系查询结果', '='*15)
x = relation.match(nodes=None, r_type='情敌')
for x_ in x:
print(x_)
=============== hate关系查询 ===============
(周芷若)-[:hate {}]->(赵敏)
=============== hate关系查询结果 ===============
(小昭)-[:情敌 {}]->(蛛儿)
(周芷若)-[:情敌 {}]->(小昭)

Process finished with exit code 0