Python 下 Flask 结合 Neo4j 构建管理系统(三)
需求
核心需求如下: * 管理系统登录 * 从 Neo4j 中获取数据信息图形化显示出来 * 节点的关系查询及溯源查询 * 对 Neo4j 进行节点的增删改
管理系统登录
首先需要在工程目录下创建 login.html
和 models.py
,前者为登录界面用于测试与 Neo4j 的连接,后者是一个用户类用于处理用户的各项操作。
本次连接采用了 Py2neo v3 库,安装可以通过 pip 安装:pip install py2neo
安装成功之后在 models.py
文件输入如下代码:
1 | from passlib.handlers import bcrypt |
authenticate()
用于连接 Neo4j 数据库,三个参数依次是地址,用户名,密码。find(self)
用户查找用户。register(self, password)
注册用户。verify_pass(self, password)
登录验证。
app.py
代码:
1 | app = Flask(__name__) |
app.secret_key
由于使用了 Session 所以必须要设置该项值。flash()
用于向网页发送信息。
数据查询
在测试完登录功能之后,首先在 templates
文件夹下创建 view.html
文件,作为登录后跳转的页面: 执行查询后相应的前端代码:
1 | $(document).ready(function () { |
后台处理代码:
app.py
代码:1
2
3
4
5
6
7
8
9
10
11
def get_search():
try:
q = request.args.get('q', 0)
f = request.args.get('f', 1)
except KeyError:
return []
else:
user = User(session.get("username"))
results = user.search_graph(q, f)
return resultsmodels.py
代码: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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67def search_graph(self, condition, flag=False):
nodes = []
rels = []
i = 0
#关系查询
query = "MATCH (m)<-[:BELONG]-(a) WHERE m.name CONTAINS \'" + condition + "\' or a.name CONTAINS \'" + condition + \
"\' RETURN properties(m) as start_node, labels(m) as labels, " \
"collect(properties(a)) as cast,collect(labels(a)) as cast_labels"
#溯源查询
query_trace = "Match (n) WHERE n.name contains \'" + condition + \
"\' MATCH path = shortestPath( (m:Website)-[:BELONG*..5]-(n) )" \
" where labels(n)='Sort' or labels(n)='GOODS'" \
" RETURN nodes(path) AS nodes, EXTRACT(node IN nodes(path) | ID(node)) AS ids " \
",EXTRACT(node IN nodes(path) | labels(node)) AS labels"
results = graph.run(query)
if flag == "true" and condition:
nodes_act = []
rels_act = []
for node_trace, id_trace, label_trace in graph.run(query_trace):
j = 0
for node_ori in node_trace:
node_act = {}
node_keys = list(node_ori.keys())
for key in node_keys:
node_act[key] = node_ori.get(key)
node_act['label'] = label_trace[j][0]
try:
target_act = nodes_act.index(node_act)
j += 1
except ValueError:
target_act = len(nodes_act)
nodes_act.append(node_act)
j += 1
if j < len(node_trace):
try:
source_act = nodes_act.index(self.get_node(node_trace[j], label_trace[j]))
except ValueError:
source_act = len(nodes_act)
rels_act.append({"source": source_act, "target": target_act})
return jsonify({"nodes": nodes_act, "links": rels_act})
for start_nodes, start_labels, end_nodes, end_labels in results:
keys = list(start_nodes.keys())
node = {}
for key in keys:
node[key] = start_nodes.get(key)
node['label'] = start_labels[0]
try:
target = nodes.index(node)
except ValueError:
nodes.append(node)
target = i
i += 1
for end_node, label in zip(end_nodes, end_labels):
end_keys = list(end_node.keys())
end = {}
for key in end_keys:
end[key] = end_node.get(key)
end['label'] = label[0]
try:
source = nodes.index(end)
except ValueError:
nodes.append(end)
source = i
i += 1
rels.append({"source": source, "target": target})
return jsonify({"nodes": nodes, "links": rels})数据的可视化采用 d3.js,具体过程参考d3.js 绘制力导向图,返回的数据格式限定为 Json 格式,nodes 保存节点信息,links 保存节点关系:
1
2{"nodes": [{'label': 'Website', 'name': 'ebay'}, {'label': 'Sort', 'name': 'Health & Beauty'}, {'label': 'Sort', 'name': 'Musical Instruments & Gear'}],
"links":[{'target': 0, 'source': 1}, {'target': 0, 'source': 2}]}
查询效果:
参考资料
Py2neo v3 Handbook