一、Cypher数据
create (小北:朋友圈{姓名:"小北", 喜欢的书类:"Poetry"}), (小菲:朋友圈{姓名:"小菲", 喜欢的书类:"Science Fiction"}), (小鹏:朋友圈{姓名:"小鹏", 喜欢的书类:"Music"}), (小颖:朋友圈{姓名:"小颖", 喜欢的书类:"Politics"}), (小兰:朋友圈{姓名:"小兰", 喜欢的书类:"Music"}), (小峰:朋友圈{姓名:"小峰", 喜欢的书类:"Travel"}), (小讯:朋友圈{姓名:"小讯", 喜欢的书类:"Poetry"}), (小东:朋友圈{姓名:"小东", 喜欢的书类:"Sequential Art"}), (小唯:朋友圈{姓名:"小唯", 喜欢的书类:"Young Adult"}), (小窦:朋友圈{姓名:"小窦", 喜欢的书类:"Poetry"}), (小齐:朋友圈{姓名:"小齐", 喜欢的书类:"Default"}), (小林:朋友圈{姓名:"小林", 喜欢的书类:"Poetry"}), (小锐:朋友圈{姓名:"小锐", 喜欢的书类:"Default"}), (小伟:朋友圈{姓名:"小伟", 喜欢的书类:"Young Adult"}), (小玲:朋友圈{姓名:"小玲", 喜欢的书类:"Business"}), (小讯)-[:认识]->(小窦), (小讯)-[:认识]->(小齐), (小讯)-[:认识]->(小林), (小讯)-[:认识]->(小鹏), (小讯)-[:认识]->(小伟), (小讯)-[:认识]->(小峰), (小菲)-[:认识]->(小鹏), (小菲)-[:认识]->(小峰), (小菲)-[:认识]->(小唯), (小峰)-[:认识]->(小北), (小峰)-[:认识]->(小兰), (小东)-[:认识]->(小林), (小东)-[:认识]->(小锐), (小东)-[:认识]->(小菲), (小鹏)-[:认识]->(小颖), (小北)-[:认识]->(小兰), (小颖)-[:认识]->(小东), (小唯)-[:认识]->(小鹏), (小唯)-[:认识]->(小锐), (小伟)-[:认识]->(小玲)
二、执行后,neo4j browser中查询效果如下
三、找出小讯和小锐之间的最短关系路径
如上图,假设给你两个人,一个人是节点小讯,另一个人是节点小锐,问他们之间的关系最短路径是什么? 或者换句话问,小讯怎么用最少的步骤联系到小锐?【前提是,小讯和小锐之间不存在任何关系,否则这种问题就没有任何意义了,你俩都有关系了,我还问个毛啊,】
如果你用肉眼观察的话,你会找到很多种小讯到达小锐的路径,比如:
1、小讯认识小峰,小菲认识小峰(如果不考虑关系的反向,则认为小峰也同样认识小菲),小菲又认识小唯,小唯认识小锐
因此这种路径下小讯联系小锐的步骤为: 小讯--小峰--小菲--小唯--小锐,路径长度4
2、同上,我们还可以找出一条长度等于3的路径:小讯--小林--小东--小锐
...... 等等,如果光靠肉眼观察的话,像这种数据少的话,勉强还可以捋下来,但是数据一多,就歇菜了,我们可以用neo4j自带的方法来算出两个节点之间存在关系的前提下的最短到达路径Path,比如:
查询出所有小讯到小锐的关系最短路径,语句如下:
MATCH n=allshortestPaths((a:朋友圈{姓名:"小讯"})-[*]-(b:朋友圈{姓名:"小锐"})) return n
查询出的graph效果如下:
下图标注的序号正是上面我们提到的长度等于3的一条路径:小讯--小林--小东--小锐
如果我们只查出最短的一条路径,我们使用shortestPath的时候只会查出一条结果,不管结果怎么样,反正都是最短路径!
语句如下:
MATCH n=shortestPath((a:朋友圈{姓名:"小讯"})-[*]-(b:朋友圈{姓名:"小锐"})) return n
四、找出小讯和小锐之间的深度等于4的路径Path
return (a)-[*4]-(b) as p
如果你查找length(path) = 8的结果会怎么样呢?
五、demo实现最短路径信息输出
Spring-Boot pom依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.appleyk</groupId> <artifactId>Spring-Boot-Neo4jAPI</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <description>Spring-Boot 集成Neo4j,实现原生JavaAPI的节点、关系操作</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.12.RELEASE</version> </parent> <properties> <java.version>1.8</java.version> <janino.version>3.0.8</janino.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 添加热部署 devtools:监听文件变动 --> <!-- 当Java文件改动时,Spring-boo会快速重新启动 --> <!-- 最简单的测试,就是随便找一个文件Ctrl+S一下,就可以看到效果 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <!-- optional=true,依赖不会传递 --> <!-- 本项目依赖devtools;若依赖本项目的其他项目想要使用devtools,需要重新引入 --> <optional>true</optional> </dependency> <!-- Spring 单元测试 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- JUnit单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.neo4j.driver/neo4j-java-driver --> <dependency> <groupId>org.neo4j.driver</groupId> <artifactId>neo4j-java-driver</artifactId> <version>1.6.1</version> </dependency> </dependencies> </project>
demo演示:
import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Test; import org.neo4j.driver.v1.AuthTokens; import org.neo4j.driver.v1.Driver; import org.neo4j.driver.v1.GraphDatabase; import org.neo4j.driver.v1.Record; import org.neo4j.driver.v1.Session; import org.neo4j.driver.v1.StatementResult; import org.neo4j.driver.v1.Value; import org.neo4j.driver.v1.types.Node; import org.neo4j.driver.v1.types.Path; import org.neo4j.driver.v1.types.Relationship; public class Neo4jBatchTest { Driver driver = GraphDatabase.driver("bolt://localhost:7687", AuthTokens.basic("neo4j", "n123")); private Session session = driver.session(); /** * 批量创建 * * @throws Exception */ @Test public void shortEstPath() throws Exception { try { String cmdSql = "MATCH n=shortestPath((a:朋友圈{姓名:'小讯'})-[*]-" + "(b:朋友圈{姓名:'小锐'})) return n"; StatementResult result = session.run(cmdSql); while (result.hasNext()) { Record record = result.next(); List<Value> values = record.values(); Map<Long, Node> nodesMap = new HashMap<>(); for (Value value : values) { if (value.type().name().equals("PATH")) { Path p = value.asPath(); System.out.println("小讯和小锐之间的关系最短路径长度为:" + p.length()); System.out.println("===================================="); Iterable<Node> nodes = p.nodes(); for (Node node : nodes) { nodesMap.put(node.id(), node); } /** * 打印最短路径里面的关系 == 关系包括起始节点的ID和末尾节点的ID,以及关系的type类型 */ Iterable<Relationship> relationships = p.relationships(); for (Relationship relationship : relationships) { Long startID = relationship.startNodeId(); Long endID = relationship.endNodeId(); String rType = relationship.type(); /** * asMap 相当于 节点的properties属性信息 */ System.out.println( nodesMap.get(startID).asMap() + "-" + rType + "-" + nodesMap.get(endID).asMap()); } } } } } catch (Exception e) { System.err.println(e.getClass() + "," + e.getMessage()); } } }
运行方法效果如下: