图数据库Neo4j学习五渲染图数据库neo4jd3
文章目录
- 1.现成的工具
- 2.Neo4j JavaScript Driver
- 3.neovis
- 4.neo4jd3
- 4.1neo4jd3和neovis对比
- 4.2获取neo4jd3
- 4.3neo4jd3的数据结构
- 4.4Spring data neo
- 4.4.1 定义返回数据格式
- 4.4.1.1NeoResults
- 4.4.1.2GraphVO
- 4.4.1.3NodeVO
- 4.4.1.4ShipVO
- 4.4.2 SDN查询解析
- 4.4.2.1 Repo查询语句
- 4.4.2.2 解析Repo查询
- 4.4.2.3返回解析结果
- 4.4.3前端处理渲染
- 4.5实现效果
本文最终技术架构:neo4jd3 + Spring boot + Spring Data Neo + neo4j
当我们刚开是接触图数据库的时候,我们进行各种关系查询,最终会得到一个拓扑图。和我们以前使用的数据库不一样的是,我们的数据库查询出来是一系列的表。

事实上,我们的图数据返回的的数据是类似于下面这样的格式的,然后通过前端(Neo4j Browser )来帮我们将返回的数据绘制成网络拓扑图。在我们之前的文章中介绍的Spring Data Neo中,返回的也都是java对象的数据

接下来本文就是介绍使用一些前端技术来帮我们将图数据库的数据返回给前端进行旋绕
1.现成的工具
比如Neo4j Browser 、Neo4j Bloom、这些官方提供的工具,免费或者有商业版权,这些工具特点都是人家已经开发好的工具,你安装上使用就行了。
例如Neo4j Browser,这些工具就好比,我们Navicat 、Sql Log、PL SQL这些客户端连接工具连接关系型数据库(mysql、oracle、post gre)等。本文就不在详细介绍。

2.Neo4j JavaScript Driver
Neo4j JavaScript Driver 是一个用于在 JavaScript 应用程序中与 Neo4j 图数据库进行通信的官方驱动程序。它提供了与 Neo4j 服务器进行连接、执行 Cypher 查询和处理查询结果等功能。我们可以在Jquery、React、Angular、Vue等前端框架中使用该驱动。
驱动安装
npm install neo4j-driver
代码示例
const neo4j = require('neo4j-driver')
const driver = neo4j.driver(uri, neo4j.auth.basic(user, password))
const session = driver.session()
const personName = 'Alice'try {const result = await session.run('CREATE (a:Person {name: $name}) RETURN a',{ name: personName })const singleRecord = result.records[0]const node = singleRecord.get(0)console.log(node.properties.name)
} finally {await session.close()
}// on application exit:
await driver.close()
官方地址:neo4j-javascript
适用于:前端直接和Neo4J直接连接
3.neovis
Neovis.js 是一个纯 JavaScript 库,使用 JavaScript 语言编写和开发开源框架。它可以在浏览器环境中直接使用,也可以与其他 JavaScript 框架和库集成,如 React、Angular 或 Vue.js
- Neovis.js 使用 Neo4j JavaScript Driver 与 Neo4j 图数据库进行通信。
- Neovis.js 在 Vis.js 的基础上构建了对 Neo4j 数据库的特定集成和功能
github地址:github-neovis.js
下面这是一个官方的示例:

Neovis.js可以通过npm安装
npm install --save neovis.js
Neovis.js可以从Neo4jLabs CDN获得
<script src="https://unpkg.com/neovis.js@2.0.2"></script>
<script src="https://unpkg.com/neovis.js@2.0.2/dist/neovis-without-dependencies.js"></script>
代码示例
需要在代码中定义每个节点,边,例如下乳,查询用户和角色
<script type="text/javascript">let neoViz;function draw() {const config = {containerId: "viz",neo4j: {serverUrl: "bolt://localhost:7687",//neo4j的用户名和密码serverUser: "neo4j",serverPassword: "neo4j",},labels: {//节点的标签1(节点类型:用户)User: {//在User类型的节点上,使用userName作为节点的显示label: "userName"},//节点的标签2(节点类型:角色)Role: {//在Role类型的节点上,使用roleName作为节点的显示label: "roleName",}//节点的标签3.......},relationships: {//关系1(边)PLAY_THE_ROLE: {value: "name"}},//Cypher语句initialCypher: "MATCH (n)-[r:PLAY_THE_ROLE]->(m) RETURN *"};neoViz = new NeoVis.default(config);neoViz.render();}
</script>
4.neo4jd3
neo4jd3使用D3.js实现Neo4j图形可视化。
github地址:githug-neo4jd3,表现效果如下:

4.1neo4jd3和neovis对比
neo4jd3和neovis是两个完全不同的组件,使用方式也不一样。
-
在底层依赖上:
neovis.js 是基于 Vis.js、neo4j JavaScript Driver 构建的,而 neo4jd3.js 基于 D3.js。 -
在功能上:
neovis.js 能够直接和neo4j 数据库相连,将数据库查询结果直接进行渲染,而neo4jd3则不和数据库相连,而是通过数据进行渲染。所以对于neo4jd3来说,只要能提供数据,就能渲染,因此我们可以使用任何技术为neo4jd3来进行获取数据,最后将数据给neo4jd3。 -
在渲染上:
neovis.js侧重于将数据库的查询语句发送给数据,然后渲染数据库返回的结果值,因此在渲染效果上存在很多的不友好一面。而neo4jd3并不关心查询语句如何编写,数据库如何查询,只对最后的数据进行渲染,因此在渲染效果上就体现的非常友好
以下是对同一个数据的查询结果进行的渲染对比,左图是neovis,右图neo4jd3,单从拓扑图上来说,左边的效果就很差

4.2获取neo4jd3
从仓库中下载代码,在dist目录下,有css和js

git clone https://github.com/eisman/neo4jd3.git

4.3neo4jd3的数据结构
我们先看官网给的两组Json,也就是需要我们的数据组织者按照如下格式进行数据格式组织
返回节点和关系的json
{"nodes": [{"id": "1","labels": ["User"],"properties": {"userId": "eisman"}},{"id": "8","labels": ["Project"],"properties": {"name": "neo4jd3","title": "neo4jd3.js","description": "Neo4j graph visualization using D3.js.","url": "https://eisman.github.io/neo4jd3"}}],"relationships": [{"id": "7","type": "DEVELOPES","startNode": "1","endNode": "8","properties": {"from": 1470002400000},"source": "1","target": "8","linknum": 1}]
}
返回绘制图的Json
{"results": [{"columns": ["user", "entity"],"data": [{"graph": {"nodes": [{"id": "1","labels": ["User"],"properties": {"userId": "eisman"}},{"id": "8","labels": ["Project"],"properties": {"name": "neo4jd3","title": "neo4jd3.js","description": "Neo4j graph visualization using D3.js.","url": "https://eisman.github.io/neo4jd3"}}],"relationships": [{"id": "7","type": "DEVELOPES","startNode": "1","endNode": "8","properties": {"from": 1470002400000}}]}}]}],"errors": []
}
4.4Spring data neo
我们现在已经知道了neo4jd3绘制图的Json格式了,现在就需要我们后台查询数据,然后返回
4.4.1 定义返回数据格式

我们当然也能通过数据格式发现,嵌套有点深,这里推荐按照这个格式来,因为不这样的话,你就得要求修改前端组建的源代码了。下面这个是前端渲染数据的一部分代码,如果后端返回的数据不按照这个格式来的话,前端这里就需要你修改代码了。

这里我避免创建很多单一属性的类,因此采用了内部类的方式,这里你不一定才用内部类,只要能返回和上面的Json格式就行
4.4.1.1NeoResults
@lombok.Data
public class NeoResults {private List<Data> results = new ArrayList<>();public NeoResults() {super();results.add(new NeoResults.Data());}@lombok.Datapublic class Data{private List<Graph> data = new ArrayList<>();public Data() {super();data.add(new Data.Graph());}@lombok.Datapublic class Graph{private GraphVO graph = new GraphVO();}}public void setNodes(List<NodeVO> nodes) {results.get(0).getData().get(0).getGraph().setNodes(nodes);} public void setRelationships(List<ShipVO> relationships) {results.get(0).getData().get(0).getGraph().setRelationships(relationships);}
}
4.4.1.2GraphVO
@Data
public class GraphVO {private List<NodeVO> nodes = new ArrayList<>();private List<ShipVO> relationships = new ArrayList<>();
}
4.4.1.3NodeVO
@Data
@AllArgsConstructor
@NoArgsConstructor
public class NodeVO{private Long id;private List<String> labels;private Map<String, Object> properties;
}
4.4.1.4ShipVO
@Data
public class ShipVO {private Long id;private String type;private Long startNode;private Long endNode;private Map<String, Object> properties;
}
4.4.2 SDN查询解析
4.4.2.1 Repo查询语句
public interface D3jsRepo extends Neo4jRepository<Object, Long> {/*** @description:查询路径:根据roadName查询Road标签查询路径* @author:hutao* @mail:hutao1@epri.sgcc.com.cn* @date:2023年8月21日 下午2:11:09*/@Query("MATCH (n:Road{name:$roadName}) MATCH path=(n)-[*]->(n1) RETURN path")List<Map<String, InternalPath.SelfContainedSegment[]>> findPathsByRoadName(@Param("roadName") String roadName);/*** @description:查询路径:根据标签label和某个属性字段查询路径,性能比较慢,谨慎使用* @author:hutao* @mail:hutao1@epri.sgcc.com.cn* @date:2023年8月21日 下午3:22:02*/@Query("MATCH (n) WHERE $label IN labels(n) AND n[$property] = $value MATCH path=(n)-[*]->(n1) RETURN path")List<Map<String, InternalPath.SelfContainedSegment[]>> findByLabelAndProperty(@Param("label") String label, @Param("property") String property, @Param("value") String value);/*** @description:查询路径:根据标主键ID查询路径* @author:hutao* @mail:hutao1@epri.sgcc.com.cn* @date:2023年8月21日 下午3:42:52*/@Query("MATCH (n) WHERE id(n) = $id MATCH path=(n)-[*]->(n1) RETURN path")List<Map<String, InternalPath.SelfContainedSegment[]>> findPathById(@Param("id") Long id);
}
4.4.2.2 解析Repo查询
@Service
public class D3jsServiceImpl implements D3jsService{@Autowiredprivate D3jsRepo d3jsRepo;/*** @description:通过节点ID找路径,以该节点为起点* @author:hutao* @mail:hutao1@epri.sgcc.com.cn* @date:2023年8月22日 上午11:17:13*/@Overridepublic NeoResults findPathsById(Long id) {NeoResults neoResult = new NeoResults();List<NodeVO> nodes = new ArrayList<>();List<ShipVO> relationships = new ArrayList<>();List<Map<String, InternalPath.SelfContainedSegment[]>> paths = d3jsRepo.findPathById(id);for (Map<String, InternalPath.SelfContainedSegment[]> path : paths) {SelfContainedSegment[] segments = path.get("path");for (SelfContainedSegment segment : segments) {addNode(nodes, segment.start());addNode(nodes, segment.end());addShip(relationships, segment.relationship());}}neoResult.setNodes(nodes);neoResult.setRelationships(relationships);return neoResult;}/*** @description:添加关系* @author:hutao* @mail:hutao1@epri.sgcc.com.cn* @date:2023年8月16日 下午1:23:54*/private void addShip(List<ShipVO> relationships, Relationship shipTemp) {ShipVO shipVO =new ShipVO();shipVO.setId(shipTemp.id());shipVO.setStartNode(shipTemp.startNodeId());shipVO.setEndNode(shipTemp.endNodeId());shipVO.setType(shipTemp.type());shipVO.setProperties(shipTemp.asMap());relationships.add(shipVO);}/*** @description:添加节点* @author:hutao* @mail:hutao1@epri.sgcc.com.cn* @date:2023年8月16日 下午2:27:37*/private void addNode(List<NodeVO> nodes, Node nodeTemp) {NodeVO noveVO = new NodeVO();List<String> labels = new ArrayList<>();nodeTemp.labels().forEach(labels::add);noveVO.setId(nodeTemp.id());noveVO.setLabels(labels);noveVO.setProperties(nodeTemp.asMap());nodes.add(noveVO);}
}
4.4.2.3返回解析结果
@GetMapping("/node/info/path/{id}")@ApiOperationSupport(order = 3)@ApiOperation(value = "3获取指定节点为起点的路径")public NeoResults queryNodeTopo(@PathVariable Long id) {NeoResults findPaths = d3jsService.findPathsById(id);return findPaths;}
4.4.3前端处理渲染
<link rel="stylesheet" href="/plugin/neod3/css/neo4jd3.min.css">
<script src="/plugin/neod3/js/d3.min.js"></script>
<script src="/plugin/neod3/js/neo4jd3.js"></script>光路起点<select id = "selectRoad" class="selectpicker" onchange = "changeRoad()" data-live-search="true" data-style="btn-info" title="请选择起点光路" ></select><div id="neo4jd3"></div>
/*** @description:选择光路触发加载光路的路径* @author:hutao* @mail:hutao1@epri.sgcc.com.cn* @date:2023年8月17日 下午2:10:18*/
function changeRoad(){let select = $('#selectRoad').val(); let url = '/node/info/path/'+select;let resultData = httpRequestForJson(url,"","GET");loadNeod3Topo(resultData);
}/*** @description:初始化节点拓扑矢量图* @author:hutao* @mail:hutao1@epri.sgcc.com.cn* @date:2023年8月17日 下午2:18:48*/
var neo4jd3
function loadNeod3Topo(resultData){neo4jd3 = new Neo4jd3('#neo4jd3', {//showLabel源代码中不存在,是我自己添加的,实现效果为:节点是否显示节点标签showLabel: true,minCollision: 100,//neo4jDataUrl: '/aaa/bbbb',neo4jData: resultData,nodeRadius: 25,onNodeDoubleClick: function(node) {console.log('double click on node: ' + JSON.stringify(node));},onRelationshipDoubleClick: function(relationship) {console.log('double click on relationship: ' + JSON.stringify(relationship));},//自动缩放zoomFit: true,});
}
4.5实现效果

相关文章:
图数据库Neo4j学习五渲染图数据库neo4jd3
文章目录 1.现成的工具2.Neo4j JavaScript Driver3.neovis4.neo4jd34.1neo4jd3和neovis对比4.2获取neo4jd34.3neo4jd3的数据结构4.4Spring data neo4.4.1 定义返回数据格式4.4.1.1NeoResults4.4.1.2GraphVO4.4.1.3NodeVO4.4.1.4ShipVO 4.4.2 SDN查询解析4.4.2.1 Repo查询语句4.…...
AI增强的社交网络·导师·电话客服……
本月共更新80条知识, 智能时代,人与人之间的差距,体现在前沿知识的整合上。 # BeFake AI AI-augmented social network AI增强的社交网络,用户使用文本提示来生成图像,拍摄自己的“AI”版本。任何人都可以创建全新的虚…...
c# Task异步使用
描述 Task出现之前,微软的多线程处理方式有:Thread→ThreadPool→委托的异步调用,虽然可以满足基本业务场景,但它们在多个线程的等待处理方面、资源占用方面、延续和阻塞方面都显得比较笨拙,在面对复杂的业务场景下&am…...
QuickLook概述和使用以及常用插件
1、QuickLook概述 QuickLook: 是可以快速预览的工具,开源、免费。通过空格键即可快速查看文件内容。 文件无需打开就可以用QuickLook一键快速预览。 说明文档:https://en.wikipedia.org/wiki/Quick_Look github地址:https://git…...
1A快恢复整流二极管型号汇总
快恢复整流二极管是二极管中的一种,开关特性好、反向恢复时间短,在开关电源、PWM脉宽调制器、变频器等电子电路中经常能看到它的身影。快恢复整流二极管的内部结构与普通PN结二极管不同,它属于PIN结型二极管,即在P型硅材料与N型硅…...
【element-ui】el-dialog改变宽度
dialog默认宽度为父元素的50%,这就导致在移动端会非常的窄,如图1,需要限定宽度。 解决方法:添加custom-class属性,然后在style中编写样式,注意,如果有scoped限定,需要加::v-deep &l…...
第三讲,实践编程 Eigen
目录 1.实践 Eigen1.1 Eigen的简介1.2 Eigen 向量和矩阵的 声明1.3 Eigen的输出操作1.4 矩阵和向量相乘 要注意数据类型 矩阵纬度1.5 矩阵的四则运算1.6 矩阵求解特征向量和特征值1.7 解方程 求逆 1.实践 Eigen 1.1 Eigen的简介 Eigen是一个 C 开源线性代数库。它提供了快…...
POI实现百万数据导出
1、概述 我们都知道Excel可以分为早期的Excel2003版本(使用POI的HSSF对象操作)和Excel2007版本(使用POI的XSSF操作),两者对百万数据的支持如下: Excel 2003:在POI中使用HSSF对象时&#…...
如何制作党建专题汇报片
通过展示党组织的凝聚力和战斗力,增强党员的组织归属感和团结合作意识。通过宣传片,可以加强党组织的凝聚力,推动党的事业发展。制作党建专题汇报片需要一定的前期准备和后期制作技巧。下面是由深圳党建专题汇报片制作公司老友记小编为您整理…...
沉浸式VR虚拟实景样板间降低了看房购房的难度
720 全景是一种以全景视角为特点的虚拟现实展示方式,它通过全景图像和虚拟现实技术,将用户带入一个仿佛置身其中的沉浸式体验中。720 全景可以应用于旅游、房地产、展览等多个领域,为用户提供更为直观、真实的体验。 在房地产领域,…...
如何在Linux环境下给Web应用配置HTTPS证书
如何在Linux环境下给Web应用配置HTTPS证书 在当今互联网时代,保护用户数据的安全性至关重要。为你的Web应用启用HTTPS协议是确保数据传输加密和身份验证的一种有效方式。本文将指导你如何在Linux环境下为Web应用程序配置HTTPS证书。 1. 获取SSL证书 首先…...
面试题-React(七):React组件通信
在React开发中,组件通信是一个核心概念,它使得不同组件能够协同工作,实现更复杂的交互和数据传递。常见的组件通信方式:父传子和子传父 一、父传子通信方式 父组件向子组件传递数据是React中最常见的一种通信方式。这种方式适用…...
MASM32编程调用 API函数RtlIpv6AddressToString,Windows 10 容易,Windows 7 折腾
一、需求分析 最近用MASM32编程更新SysInfo,增加对IPv6连接信息的收集功能,其中涉及到 MIB_TCP6ROW_OWNER_MODULE 结构体: ;typedef struct _MIB_TCP6ROW_OWNER_MODULE { ; UCHAR ucLocalAddr[16]; ; DWORD dwLocalScope…...
为什么使用Nacos而不是Eureka(Nacos和Eureka的区别)
文章目录 前言一、Eureka是什么?二、Nacos是什么?三、Nacos和Eureka的区别3.1 支持的CAP3.2连接方式3.3 服务异常剔除3.4 操作实例方式 总结 前言 为什么如今微服务注册中心用Nacos相对比用Eureka的多了?本文章将介绍他们之间的区别和优缺点…...
Python作业一
目录 1、用循环语句求122333444455555的和 2、求出2000-2100的所有闰年,条件是四年一闰,百年不闰,四百年再闰 3、输入两个正整数,并求出它们的最大公约数和最小公倍数 4、求出100以内的所有质数 5、求100以内最大的10个质数的…...
protobuf概览
protobuf protobuf是由谷歌推出的二进制序列化与反序列化库对象。也是著名GRPC的底层依赖,它独立于平台及语言的序列化与反序列化标准库。 相关网址 protobuf IDL描述protobuf 开源库grpc-知乎grpc官方示例 安装protobuf可以使用vcpkg进行简易安装依赖ÿ…...
<C++> SSE指令集
SSE指令集 include库 #include <mmintrin.h> //MMX #include <xmmintrin.h> //SSE(include mmintrin.h) #include <emmintrin.h> //SSE2(include xmmintrin.h) #include <pmmintrin.h> //SSE3(include emmintrin.h) #include <tmmintrin.h> /…...
cortex-A7核LED灯实验--STM32MP157
实验目的:实现LED1 / LED2 / LED3三盏灯工作 一,分析电路图 1,思路 分析电路图可知: 网络编号 引脚编号 LED1 PE10 LED2 > PF10 LED3 > PE8 2,工作原理: 写1:LED灯亮…...
WPF实战项目十三(API篇):备忘录功能api接口、优化待办事项api接口
1、新建MenoDto.cs /// <summary>/// 备忘录传输实体/// </summary>public class MenoDto : BaseDto{private string title;/// <summary>/// 标题/// </summary>public string Title{get { return title; }set { title value; }}private string con…...
clickhouse(十四、分布式DDL阻塞及同步阻塞问题)
文章目录 一、分布式ddl 阻塞、超时现象验证方法解决方案 二、副本同步阻塞现象验证解决方案 一、分布式ddl 阻塞、超时 现象 在clickhouse 集群的操作中,如果同时执行一些重量级变更语句,往往会引起阻塞。 一般是由于节点堆积过多耗时的ddl。然后抛出…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡
何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践,很多人以为AI已经强大到不需要程序员了,其实不是,AI更加需要程序员,普通人…...
RLHF vs RLVR:对齐学习中的两种强化方式详解
在语言模型对齐(alignment)中,强化学习(RL)是一种重要的策略。而其中两种典型形式——RLHF(Reinforcement Learning with Human Feedback) 与 RLVR(Reinforcement Learning with Ver…...
