对Neo4j导出数据做知识图谱可视化 D3库实现

    技术2024-05-26  143

    目录

    一、引言二、从Neo4j导出数据三、前端实现1. 初始化D3并读取本地数据2. 分离出节点和关系数据3. 可视化效果展示

    一、引言

    好久没用D3库作可视化了,现在主要是用百度的echarts库,在项目中做简单的图表太方便了。但像是做关系图其实用echarts也很方便,这次用D3实现主要是复习一下以前做的东西,顺便记录一下。

    以下是我参考到的实例代码:

    D3官方图实例参考echarts做关系图实例参考

    二、从Neo4j导出数据

    我们先通过Cypher查询将数据从Neo4j中查询出来,Neo4j构建和查询可以参考我上篇博客 基于Neo4j的外贸企业关系图谱做企业相似度查询

    由于原Cypher语句比较长,通过下面的查询导出的格式也是一样的,根据自己的关系查询进行修改即可:

    MATCH p=(n:Enterprise)-[]->() RETURN p limit 20

    查询后的结果如下,点击右上角下载图标,导出为JSON格式

    可以进入JSON在线解析,查看导出的JSON格式:

    三、前端实现

    1. 初始化D3并读取本地数据

    新建好一个Web项目后,先把D3的JS库导入进来,再通过d3.json()来读取我们的json文件。

    可以通过本地方式导入

    <!-- 增加D3元素库 --> <script src="js/d3.v4.min.js"></script>

    如果不想下到本地,也可以通过CDN方式直接导入

    <!-- 增加D3元素库 --> <script src="https://cdn.bootcdn.net/ajax/libs/d3/4.9.1/d3.min.js"></script>

    导入D3后,就可以通过d3.json方法读取本地的json文件:

    var graph; //d3.json获取数据 d3.json("data/records.json", function(error, data) { if(error) throw error; graph = data; console.log(graph[0].p); }

    先运行结果,查看控制台打印的结果如下: `

    2. 分离出节点和关系数据

    还是先去D3官方图实例参考分析一下标准数据格式,从下图可以看到 data 分为 nodes 和 links 两部分,因为在D3中节点和关系是分开渲染的,渲染过后会自动在各个部分内生成位置坐标的属性。 此时我们需要将neo4j导出的数据做标准化,使数据格式符合D3标准。 (需要注意一个坑:要对json数据做去重处理,不然D3在渲染时无法将节点关系弄出来,原理其实就是节点的唯一标识产生了冲突,我们要保证节点的唯一性) 以下是标准化的代码,将json数据分离到nodes和links两部分,为数据绑定打好基础:

    // 图数据 var graph; let nodes =[]; let links = []; // 存放节点和关系 let nodeSet = []; // 存放去重后nodes的id //d3.json获取数据 d3.json("data/records.json", function(error, data) { if(error) throw error; graph = data; console.log(graph[0].p); for (let item of graph) { // console.log(item.p.start instanceof Array) // console.log(item.p) // 重新更改data格式 if(nodeSet.indexOf(item.p.start.identity) == -1){ nodeSet.push(item.p.start.identity) nodes.push({ id: item.p.start.identity, label: item.p.start.labels[0], properties: item.p.start.properties }) } if(nodeSet.indexOf(item.p.end.identity) == -1){ nodeSet.push(item.p.end.identity) nodes.push({ id: item.p.end.identity, label: item.p.end.labels[0], properties: item.p.end.properties }) } links.push({ source: item.p.segments[0].relationship.start, target: item.p.segments[0].relationship.end, type: item.p.segments[0].relationship.type, properties: item.p.segments[0].relationship.properties }) } console.log(nodes) console.log(links) }

    3. 可视化效果展示

    数据处理好之后,只需要把数据绑定到D3上即可,至于展示部分官网参考代码已经有了,在此不再做详细展开,后面也可以参考我的代码注释理解。

    最终展示出的效果如下:

    从二图中可以看到可视化还做了一些事件处理,目前完成了拖拽事件、鼠标进入、鼠标离开三个事件。当鼠标放到节点上时,在右边会展示节点信息,并隐藏与该节点无关的其他节点。

    最后,加了个节点文字切换和搜索功能,之前的节点全挨在一起,于是又加了个碰撞检测模型,最终效果如下:

    像这种力导向关系图可以结合多个力学模型自行扩充,其他的效果可以自行拓展:(官方参考的力模型)

    Centering(向心力)Collision(碰撞检测)Links(弹簧力)Many-Body(电荷力)Positioning(定位力)

    个人实现代码(仅供参考): github地址:https://github.com/CoderWanp/neo4j-d3-graph

    直接看页面效果: Demo展示:https://coderwanp.github.io/neo4j-d3-graph/

    Processed: 0.010, SQL: 10