用可视化的方式来展示网络关系图是一件挺有趣的事情,在选定用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分为两种,一种叫做cytoscapedesktop,是一个桌面软件,可以把数据导入然后生成可视化的网络图进行分析;另一种叫做cytoscape.js,是一个javascript库,主要给开发人员使用,来在网页上生成可视化的网络图。我们要用的是后者。
neo4j有三个概念:图(Graph),节点(Node)和关系(Relationship)。cytoscape.js也有三个对应的概念:图(用方法cytoscape()来生成),节点(Node)和边(Edge)。
下面是用cytoscape.js画图的典型方法。
varcy=cytoscape({container:document.getElementById('cy'),elements:{nodes:[/*...*/],edges:[/*...*/]},style:[/*...*/],layout:{name:'cose'}});主要是用cytoscape()函数生成cy,并填充其各种属性(如:container,elements,style,layout等等)。让我们来写个简单的网页来生成下面的图。所有的代码都在一个html文件中,你可以把它存成index.html,然后用浏览器直接打开看效果。
代码18行,container属性被设置为用
代码30-36行,elements属性包含的是图里的节点和边。
节点包括多个属性值,如:{data:{id:'172',name:'TomCruise',label:'Person'}}。其中只有id是保留属性必须填,其它如name还有label都是我们自定义的属性,你可以自定义任意多的属性。
边和节点的属性值很类似,如:{data:{source:'172',target:'183',relationship:'Acted_In'}}。边也有id是保留属性但不是必须的,source/target都是保留属性,source表示开始节点(startnode)的id值,target是结束节点(endnode)的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:'TomCruise',label:'Person'}})里name值,也就是’TomCruise’。
{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_neo4jclone。
C:\cytoscape_neo4j|app.py|+---static|+---css||style.css|||\---js|code.js|cytoscape.min.js|jquery-1.11.2.min.js|\---templatesindex.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){varstyle=[{selector:'node[label="Person"]',css:{'background-color':'#6FB1FC'}},{selector:'node[label="Movie"]',css:{'background-color':'#F5A45D'}}];
varcy=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":"WelcometotheRealWorld","title":"TheMatrix"}},{"data":{"born":1962,"id":"189","label":"Person","name":"TomCruise"}},/*..*/]}}我们只需要在代码第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-8fromflaskimportFlask,jsonify,render_templatefrompy2neoimportGraph
app=Flask(__name__)graph=Graph()
defbuildNodes(nodeRecord):data={"id":str(nodeRecord.n._id),"label":next(iter(nodeRecord.n.labels))}data.update(nodeRecord.n.properties)
return{"data":data}
defbuildEdges(relationRecord):data={"source":str(relationRecord.r.start_node._id),"target":str(relationRecord.r.end_node._id),"relationship":relationRecord.r.rel.type}
@app.route('/')defindex():returnrender_template('index.html')
@app.route('/graph')defget_graph():nodes=map(buildNodes,graph.cypher.execute('MATCH(n)RETURNn'))edges=map(buildEdges,graph.cypher.execute('MATCH()-[r]->()RETURNr'))
returnjsonify(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)RETURNn'))。
graph.cypher.execute('MATCH(n)RETURNn')获取了Movie库的所有节点。map()对每个节点调用buildNodes(nodeRecord)函数,生成数组nodes(例如[{"data":{"born":1962,"id":"189","label":"Person","name":"TomCruise"}},/*node2*/,/*node3*/,...])。
代码28行,edges=map(buildEdges,graph.cypher.execute('MATCH()-[r]->()RETURNr'))生成了所有的边。
代码30行,用Flask的jsonify函数把elements转成JSON格式返回给前端。
运行我们的代码吧!写完了所有的代码,是时候来看看我们的劳动成果了。让我们来启动我们的网站,看看Movie库的网络关系图显示出来的效果吧。你需要:
运行如下命令启动Flask网站。
这里看到的关系图只是关系图的一小部分,你可以用鼠标滚轮来缩小放大来看到全貌。
到此,大家应该通过这三篇博客了解到如何利用neo4j,Flask,py2neo,cytoscape.js来显示neo4j的网络关系图了。