动手构建地铁关系网,实现最短路径查询
一、前言
打开手机‘北京地铁’APP,输入起始点:霍营,终点:北京南站,发现系统给我们推荐了两条路线。 最短时间路线与最少换乘路线,并且分别给出了耗时与乘坐里程费。看到这里,不禁开启了靓仔疑问,假如给你地铁站相关数据,如何构建这样的关系网络呢?(尽量少写代码,毕竟我这个人懒的不行,花最少的功夫,整最炫的效果,咦)
1.整理地铁站点数据,处理成echarts图表所需要的结构 2.整理地铁站点数据,自己写代码实现,能实现(好累啊...) 3.整理地铁站点数据,导入 Neo4j 中,点击查看
分析:方案一,不仅要处理数据还要搞echarts样式,算了吧。方案二,直接PASS,还是方案三省力,正好我的电脑上之前安装过 Neo4j 图数据库,哈哈哈,开搞开搞! 软件下载地址:http://doc.we-yun.com:1008/neo4j-chs 软件安装教程:https://www.cnblogs.com/jstarseven/p/9546555.html
二、数据准备
既然需要展示地铁关系,那么首先需要的就是北京所有地铁站的信息,以及站点之间的关系,距离,耗时。搜索了一圈,最后在北京地铁官方网站,发现了全部地铁线路,站点名称,站点与站点之间距离等信息。但是缺少了具体站点与站点之间的乘车耗时,行吧,先将就着用吧!具体数据样例如下:
数据来源地址:https://www.bjsubway.com/station/zjgls/#
站点关系
一共18条线路,一顿复制粘贴和 Notepad++ 文本替换之后,我们得到了一个 Excel文件,包含了所有站点之间的关系数据,如下:
获取站点
复制所有站点进入Excel文件的某一个sheet,选择数据去重,得到所有站点名称。
处理CSV
将站点关系与站点数据处理成CSV文件格式,方便导入 Neo4j 数据库中,建立图节点与关系。操作也就是 notepad++ 替换‘ ’为‘,’,另存为 .CSV 文件,具体得到下列文件。(因为方便 Neo4j 数据库不同的路线显示不同的颜色,我特地将站点关系数据拆解成了多个地铁线的CSV文件,如果不考虑显示,可以一个CSV文件,导入站点关系即可)
备注:将所有CSV文件,放入 Neo4j 安装目录下的 import 文件夹中(没有就新建),如下:
文件下载地址:https://files-cdn.cnblogs.com/files/jstarseven/subway.zip
三、建立地铁关系网
Neo4j 支持导入本地以及网络资源中的 CSV 文件数据,并且可以从CSV文件数据中,直接建立图形节点以及节点关系。具体 cypher 语句,如下:
建立地铁站点
LOAD CSV WITH HEADERS FROM "file:///station.csv" AS line
MERGE (p:Station{id:line.id,name:line.name});
建立站点连接
LOAD CSV WITH HEADERS FROM "file:///line1.csv" AS line1
match (from1:Station{name:line1.sn}),(to1:Station{name:line1.en})
merge (from1)-[r1:一号线{jl:line1.jl,xl:line1.xl}]->(to1);
LOAD CSV WITH HEADERS FROM "file:///line2.csv" AS line2
match (from2:Station{name:line2.sn}),(to2:Station{name:line2.en})
merge (from2)-[r2:二号线{jl:line2.jl,xl:line2.xl}]->(to2);
LOAD CSV WITH HEADERS FROM "file:///line4.csv" AS line4
match (from4:Station{name:line4.sn}),(to4:Station{name:line4.en})
merge (from4)-[r4:四号线{jl:line4.jl,xl:line4.xl}]->(to4);
LOAD CSV WITH HEADERS FROM "file:///line5.csv" AS line5
match (from5:Station{name:line5.sn}),(to5:Station{name:line5.en})
merge (from5)-[r5:五号线{jl:line5.jl,xl:line5.xl}]->(to5);
LOAD CSV WITH HEADERS FROM "file:///line6.csv" AS line6
match (from6:Station{name:line6.sn}),(to6:Station{name:line6.en})
merge (from6)-[r6:六号线{jl:line6.jl,xl:line6.xl}]->(to6);
LOAD CSV WITH HEADERS FROM "file:///line7.csv" AS line7
match (from7:Station{name:line7.sn}),(to7:Station{name:line7.en})
merge (from7)-[r7:七号线{jl:line7.jl,xl:line7.xl}]->(to7);
LOAD CSV WITH HEADERS FROM "file:///line8.csv" AS line8
match (from8:Station{name:line8.sn}),(to8:Station{name:line8.en})
merge (from8)-[r8:八号线{jl:line8.jl,xl:line8.xl}]->(to8);
LOAD CSV WITH HEADERS FROM "file:///line9.csv" AS line9
match (from9:Station{name:line9.sn}),(to9:Station{name:line9.en})
merge (from9)-[r9:九号线{jl:line9.jl,xl:line9.xl}]->(to9);
LOAD CSV WITH HEADERS FROM "file:///line10.csv" AS line10
match (from10:Station{name:line10.sn}),(to10:Station{name:line10.en})
merge (from10)-[r10:十号线{jl:line10.jl,xl:line10.xl}]->(to10);
LOAD CSV WITH HEADERS FROM "file:///line13.csv" AS line13
match (from13:Station{name:line13.sn}),(to13:Station{name:line13.en})
merge (from13)-[r13:十三号线{jl:line13.jl,xl:line13.xl}]->(to13);
LOAD CSV WITH HEADERS FROM "file:///line14.csv" AS line14
match (from14:Station{name:line14.sn}),(to14:Station{name:line14.en})
merge (from14)-[r14:十四号线{jl:line14.jl,xl:line14.xl}]->(to14);
LOAD CSV WITH HEADERS FROM "file:///line15.csv" AS line15
match (from15:Station{name:line15.sn}),(to15:Station{name:line15.en})
merge (from15)-[r15:十五号线{jl:line15.jl,xl:line15.xl}]->(to15);
LOAD CSV WITH HEADERS FROM "file:///linebt.csv" AS linebt
match (frombt:Station{name:linebt.sn}),(tobt:Station{name:linebt.en})
merge (frombt)-[rbt:八通线{jl:linebt.jl,xl:linebt.xl}]->(tobt);
LOAD CSV WITH HEADERS FROM "file:///linecp.csv" AS linecp
match (fromcp:Station{name:linecp.sn}),(tocp:Station{name:linecp.en})
merge (fromcp)-[rcp:昌平线{jl:linecp.jl,xl:linecp.xl}]->(tocp);
LOAD CSV WITH HEADERS FROM "file:///lineyz.csv" AS lineyz
match (fromyz:Station{name:lineyz.sn}),(toyz:Station{name:lineyz.en})
merge (fromyz)-[ryz:亦庄线{jl:lineyz.jl,xl:lineyz.xl}]->(toyz);
LOAD CSV WITH HEADERS FROM "file:///linedx.csv" AS linedx
match (fromdx:Station{name:linedx.sn}),(todx:Station{name:linedx.en})
merge (fromdx)-[rdx:大兴线{jl:linedx.jl,xl:linedx.xl}]->(todx);
LOAD CSV WITH HEADERS FROM "file:///linefs.csv" AS linefs
match (fromfs:Station{name:linefs.sn}),(tofs:Station{name:linefs.en})
merge (fromfs)-[rfs:房山线{jl:linefs.jl,xl:linefs.xl}]->(tofs);
LOAD CSV WITH HEADERS FROM "file:///linejc.csv" AS linejc
match (fromjc:Station{name:linejc.sn}),(tojc:Station{name:linejc.en})
merge (fromjc)-[rjc:机场线{jl:linejc.jl,xl:linejc.xl}]->(tojc);
执行效果
备注:Neo4j浏览器需要开启多语句执行配置,否则会报语句执行错误,配置界面如下:
1.Neo4j浏览器配置
2.cypher语句执行过程
3.地铁关系网效果
四、路径检索
以‘霍营’与‘北京南站’地铁站为例,检索具体一下路径:
最少站点路径
MATCH (p1:Station {name:"霍营"}),(p2:Station{name:"北京南站"}),p=shortestpath((p1)-[*]-(p2)) RETURN p
最短路程路径
MATCH p=(b:Station{name:"霍营"})-[*..20]->(d:Station{name:"北京南站"}) WITH p,reduce(s = 0, r IN rels(p) | s + r.jl) AS dist return p ORDER BY dist DESC limit 1
最少耗时路径
很遗憾,因为没有找到北京地铁每站之间具体的耗时数据,所以此处检索不出来,行吧,我太难了。
五、总结
1)数据整理涉及节点数据,节点关系数据,可在导入CSV时一并创建; 2)Cypher 是 借鉴了sql语句的 Neo4j 数据库操作语句; 3)(a)-[*..20]->(b):表示路径长度的最大值是20,起始节点是a,终止节点是b; 4)一次执行多条语句,Neo4j浏览器需要开启多语句执行配置;
over
- [Hadoop大数据]——Hive连接JOIN用例详解
- 扑克牌的顺子
- 数组前半部分和后半部分有序的全排序
- restful Api 风格契约设计器:Swagger-editor和swagger-ui的应用
- 循序渐进,了解Hive是什么!
- 二叉树的遍历——递归和非递归
- vue组件,撸第一个
- 手把手教你搭建Hive Web环境
- 成员以其在类中声明的顺序构造
- 《Spark大数据处理》—— 读后总结
- NHibernate联合主键详细示例
- 《Spark快速大数据分析》—— 第三章 RDD编程
- 日本首富孙正义预言30年后的世界:我非常激动,感觉睡觉都是在浪费时间
- 《Spark快速大数据分析》—— 第五章 数据读取和保存
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 树莓派基础实验15:电位器传感器实验
- java JDBC数据库连接池技术(Druid ,c3p0)
- Fail to start qos server: dubbo version: current host: java.net.BindException:
- JAVA JDBC Template的使用
- 《sql必知必会》——读书笔记(2)
- 2.通过QOpenGLWidget绘制三角形
- 树莓派基础实验16:霍尔传感器实验
- 1.opengl绘制三角形
- dubbo本地直连调试注意点
- Tomcat的使用及服务器的一些基础知识
- fastJson 之JSONObject.toJavaObject()方法不能解析嵌套自定义list对象
- 文件包含漏洞学习总结(结尾有实例)
- 树莓派基础实验17:温度传感器实验
- Java Servlet详解(体系结构+注解配置+生命周期)
- RabbitMq如何确保消息不丢失