用可視化的方式來展示網絡關系圖是一件挺有趣的事情,在選定用cytoscape.js來顯示neo4j圖形數據庫的數據后我做了一個原型,並用下面三篇博客來記錄了做原型的過程。
用cytoscape.js展示neo4j網絡關系圖 - 1. Flask
用cytoscape.js展示neo4j網絡關系圖 - 2. py2neo
用cytoscape.js展示neo4j網絡關系圖 - 3. cytoscape.js(這篇博客)
要完成的功能
要把neo4j數據庫里面的Movie數據正確的顯示到前端,我們需要完成如下的功能。
搭建基於Flask的簡單網站
用py2neo來獲取neo4j的節點及關系
用cytoscape.js來顯示網絡關系圖
上一篇博客介紹了如何用py2neo來獲取neo4j的節點及關系,現在我們要用cytoscape.js來把用neo4j取得的節點和關系顯示到網頁上。
先看看cytoscape.js是什么
cytoscape是一個網絡圖的可視化工具,大量的生物分子/基因領域的公司用它來做可視化分析。由於它的通用性,慢慢的也被其他領域的人用來做網絡的可視化和分析。cytoscape分為兩種,一種叫做cytoscape desktop,是一個桌面軟件,可以把數據導入然后生成可視化的網絡圖進行分析;另一種叫做cytoscape.js,是一個javascript庫,主要給開發人員使用,來在網頁上生成可視化的網絡圖。我們要用的是后者。
neo4j有三個概念:圖(Graph),節點(Node)和關系(Relationship)。cytoscape.js也有三個對應的概念:圖(用方法cytoscape()來生成),節點(Node)和邊(Edge)。
下面是用cytoscape.js畫圖的典型方法。
var cy = cytoscape({
container: document.getElementById('cy'),
elements: {
nodes: [/* ... */ ],
edges: [/* ... */ ]
},
style: [ /* ... */ ],
layout: { name: 'cose' }
});
主要是用cytoscape()函數生成cy,並填充其各種屬性(如:container, elements, style, layout等等)。讓我們來寫個簡單的網頁來生成下面的圖。所有的代碼都在一個html文件中,你可以把它存成index.html,然后用瀏覽器直接打開看效果。
<!DOCTYPE html>
<html>
<head>
<title>Learning Cytoscape.js</title>
<style type="text/css">
/* cytoscape graph */
#cy {
height: 300px;
width: 400px;
background-color: #f9f9f9;
}
</style>
<script src="http://cdn.bootcss.com/jquery/1.11.2/jquery.min.js"></script>
<script src="http://cdn.bootcss.com/cytoscape/2.3.16/cytoscape.min.js"></script>
<script>
$(function(){
cytoscape({
container: document.getElementById('cy'),
style: [
{ selector: 'node[label = "Person"]',
css: {'background-color': '#6FB1FC', 'content': 'data(name)'}
},
{ selector: 'node[label = "Movie"]',
css: {'background-color': '#F5A45D', 'content': 'data(title)'}
},
{ selector: 'edge',
css: {'content': 'data(relationship)', 'target-arrow-shape': 'triangle'}
}
],
elements: {
nodes: [
{data: {id: '172', name: 'Tom Cruise', label: 'Person'}},
{data: {id: '183', title: 'Top Gun', label: 'Movie'}}
],
edges: [{data: {source: '172', target: '183', relationship: 'Acted_In'}}]
},
layout: { name: 'grid'}
});
});
</script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
代碼5-12行設置圖的屬性,這是一個長400px寬300px底色灰色的圖。代碼15-40行我們調用cytoscape()函數並初始化它來完成關系圖的繪制。
代碼18行,container屬性被設置為用<div id="cy"></div>這個div來繪制圖。
代碼30-36行,elements屬性包含的是圖里的節點和邊。
節點包括多個屬性值,如:{data: {id: '172', name: 'Tom Cruise', label: 'Person'}}。其中只有id是保留屬性必須填,其它如name還有label都是我們自定義的屬性,你可以自定義任意多的屬性。
邊和節點的屬性值很類似,如:{data: {source: '172', target: '183', relationship: 'Acted_In'}}。邊也有id是保留屬性但不是必須的,source/target都是保留屬性,source表示開始節點(start node)的id值,target是結束節點(end node)的id值,relationship是我們自定義的屬性。
有了節點和邊的數據,那它們顯示出來是什么樣子的則是由代碼19-29行的style屬性決定的。style由多個如下的(selector + css)樣式組成。
{ selector: 'node[label = "Person"]',
css: {'background-color': '#6FB1FC','content': 'data(name)}
}
selector屬性選擇要修改樣式的元素,上面我們選擇了label = "Person"的節點。css設置樣式。這里我們設置Person節點的背景顏色為’#6FB1FC’。content屬性決定節點上顯示的文字是什么,我們用了一個data()函數來從節點數據里取出自定義節點({data: {id: '172', name: 'Tom Cruise', label: 'Person'}})里name值,也就是’Tom Cruise’。
{ selector: 'edge',
css: {'content': 'data(relationship)', 'target-arrow-shape': 'triangle'}
}
邊(edge)的style和節點有點不一樣。我們選擇顯示的文字是relationship的值。而且我們需要把邊的三角形箭頭顯示出來('target-arrow-shape': 'triangle')。
代碼37行,layout屬性。layout布局網絡圖里的節點顯示的位置。你可以選擇不同類型的layout把整個網絡顯示成樹形,圓形,網格,力導向圖等等。我們隨便選了一個’grid’網格布局。
開始寫代碼
我們再回過頭來看看前面我們建好的Flask網站的目錄結構。下面所有的源代碼都可以從我的github項目cytoscape_neo4j clone。
C:\cytoscape_neo4j
| app.py
|
+---static
| +---css
| | style.css
| |
| \---js
| code.js
| cytoscape.min.js
| jquery-1.11.2.min.js
|
\---templates
index.html
我們需要修改app.py和code.js。先看看code.js,它從app.py獲取JSON數據,然后調用cytoscape()函數顯示網絡圖。
用cytoscape.js來顯示Movie網絡關系圖
下面是code.js的代碼。(源代碼:cytoscape_neo4j/static/js/code.js)
$(function(){
$.get('/graph', function(result) {
var style = [
{ selector: 'node[label = "Person"]', css: {'background-color': '#6FB1FC'}},
{ selector: 'node[label = "Movie"]', css: {'background-color': '#F5A45D'}}
];
var cy = cytoscape({
container: document.getElementById('cy'),
style: style,
layout: { name: 'cose', fit: false },
elements: result.elements
});
}, 'json');
});
和前面講的代碼大同小異。代碼第2行,用jQuery的$.get('/graph', function(result) {}, 'json')方法從網站后端的’/graph’路徑獲得JSON數據存在result中。JSON數據的內容如下:
{
"elements": {
"edges": [
{"data": {"relationship": "ACTED_IN", "source": "174", "target": "327"}},
{"data": {"relationship": "ACTED_IN", "source": "174", "target": "273"}},
/* ... */
],
"nodes": [
{"data": {"id": "173", "label": "Movie", "released": 1999, "tagline": "Welcome to the Real World", "title": "The Matrix"}},
{"data": {"born": 1962, "id": "189", "label": "Person", "name": "Tom Cruise"}},
/* .. */
]
}
}
我們只需要在代碼第12行,elements: result.elements把result里的elements復給elements屬性就好。
代碼3-6行,style和前面講到的差不多,這次我們並沒有設content屬性,所以顯示的節點上不會有文字。
下面我們看看app.py是如何把neo4j的數據轉成符合cytoscape要求的JSON的。
把neo4j的數據轉成cytoscape需要的JSON數據
下面是app.py的代碼。(源代碼:cytoscape_neo4j/app.py)
# coding=utf-8
from flask import Flask, jsonify, render_template
from py2neo import Graph
app = Flask(__name__)
graph = Graph()
def buildNodes(nodeRecord):
data = {"id": str(nodeRecord.n._id), "label": next(iter(nodeRecord.n.labels))}
data.update(nodeRecord.n.properties)
return {"data": data}
def buildEdges(relationRecord):
data = {"source": str(relationRecord.r.start_node._id),
"target": str(relationRecord.r.end_node._id),
"relationship": relationRecord.r.rel.type}
return {"data": data}
@app.route('/')
def index():
return render_template('index.html')
@app.route('/graph')
def get_graph():
nodes = map(buildNodes, graph.cypher.execute('MATCH (n) RETURN n'))
edges = map(buildEdges, graph.cypher.execute('MATCH ()-[r]->() RETURN r'))
return jsonify(elements = {"nodes": nodes, "edges": edges})
if __name__ == '__main__':
app.run(debug = True)
這段代碼用到了很多py2neo的函數,如果不熟悉的可以回到前一個博客看看它們的用法。
code.js中的$.get('/graph', function(result) {}, 'json')會調用到代碼中的25-30行。
代碼27行,nodes = map(buildNodes, graph.cypher.execute('MATCH (n) RETURN n'))。
graph.cypher.execute('MATCH (n) RETURN n')獲取了Movie庫的所有節點。map()對每個節點調用buildNodes(nodeRecord)函數,生成數組nodes (例如[{"data": {"born": 1962, "id": "189", "label": "Person", "name": "Tom Cruise"}}, /* node2*/, /* node3 */, ...])。
代碼28行,edges = map(buildEdges, graph.cypher.execute('MATCH ()-[r]->() RETURN r'))生成了所有的邊。
代碼30行,用Flask的jsonify函數把elements轉成JSON格式返回給前端。
運行我們的代碼吧!
寫完了所有的代碼,是時候來看看我們的勞動成果了。讓我們來啟動我們的網站,看看Movie庫的網絡關系圖顯示出來的效果吧。你需要:
啟動neo4j server
啟動Flask網站
用瀏覽器瀏覽網頁http://127.0.0.1:5000/
雙擊C:\neo4j-community-2.2.1\bin\Neo4j.bat啟動neo4j server。
運行如下命令啟動Flask網站。
用瀏覽器瀏覽網頁http://127.0.0.1:5000/,你就可以看到畫出來的網絡關系圖了。
這里看到的關系圖只是關系圖的一小部分,你可以用鼠標滾輪來縮小放大來看到全貌。
到此,大家應該通過這三篇博客了解到如何利用neo4j, Flask, py2neo, cytoscape.js來顯示neo4j的網絡關系圖了。
————————————————
https://blog.csdn.net/zhongzhu2002/article/details/46049197