package com.fly.demo;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.traversal.Evaluators;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.graphdb.traversal.Traverser;
import org.neo4j.io.fs.FileUtils;
import java.io.File;
import java.io.IOException;
/**
* 图的遍历
*/
public class Frient {
// 关系类型
public enum RelTypes implements RelationshipType {
HOME_NODE,
KNOWS,
CO_WORKER
}
private static final File DB_PATH = new File("demo/neo4j-td");
private GraphDatabaseService graphDb;
// home节点id
private long homeNodeId;
public static void main(String...args) throws IOException {
Frient matrix = new Frient();
matrix.setUp();
System.out.println(matrix.printFriends());
System.out.println(matrix.printWorkers());
matrix.shutdown();
}
public void setUp() throws IOException{
FileUtils.deleteRecursively(DB_PATH);
graphDb = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
registerShutdownHook();
createNodespace();
}
private Node getEndNode(Long id) {
return graphDb.getNodeById(id)
.getSingleRelationship(RelTypes.HOME_NODE, Direction.OUTGOING)
.getEndNode();
}
public String printFriends(){
try (Transaction tx = graphDb.beginTx()) {
Node neoNode = getEndNode(homeNodeId);
int numberOfFriends = 0;
StringBuilder output = new StringBuilder(neoNode.getProperty("name") + "'s friends:\n");
Traverser friendsTraverser = getFriends(neoNode);
for (Path friendPath : friendsTraverser) {
output.append("At depth ").append(friendPath.length()).append(" => ").append(friendPath.endNode()
.getProperty("name")).append("\n");
numberOfFriends++;
}
output.append("Number of friends found: ").append(numberOfFriends).append("\n");
return output.toString();
}
}
public String printWorkers(){
try (Transaction tx = graphDb.beginTx()){
StringBuilder output = new StringBuilder("co-worker:\n");
int number = 0;
Traverser traverser = findWorker(getEndNode(homeNodeId));
for (Path hackerPath : traverser) {
output.append("At depth ").append(hackerPath.length()).append(" => ").append(hackerPath.endNode()
.getProperty("name")).append("\n");
number++;
}
output.append("Number of co-worker found: ").append(number).append("\n");
return output.toString();
}
}
//广度优先
private Traverser getFriends(final Node person) {
TraversalDescription td = graphDb.traversalDescription()
.breadthFirst() //设置使用广度优先遍历算法
.relationships(RelTypes.KNOWS, Direction.OUTGOING) // 关系函数为KNOWS,同时设置单向查找方向
.evaluator(Evaluators.excludeStartPosition()); // 设置评估函数,从开始节点查找
return td.traverse(person);
}
//深度优先
private Traverser getFriendsDepth(final Node person) {
TraversalDescription td = graphDb.traversalDescription()
.depthFirst()
.relationships(RelTypes.KNOWS, Direction.OUTGOING)
.evaluator(Evaluators.excludeStartPosition());
return td.traverse(person);
}
private Traverser findWorker(final Node startNode) {
TraversalDescription td = graphDb.traversalDescription()
.depthFirst() // 使用深度优先遍历算法
// 使用2个关系函数来查找路径
.relationships(RelTypes.CO_WORKER, Direction.OUTGOING)
.relationships(RelTypes.KNOWS, Direction.OUTGOING)
// 查找最终节点的CO_WORKER关系
.evaluator(Evaluators.includeWhereLastRelationshipTypeIs(RelTypes.CO_WORKER));
return td.traverse(startNode);
}
public void createNodespace() {
try (Transaction tx = graphDb.beginTx()) {
Node home = graphDb.createNode();
homeNodeId = home.getId();
Node user = graphDb.createNode();
user.setProperty("name", "User");
home.createRelationshipTo(user, RelTypes.HOME_NODE);
Node one = graphDb.createNode();
one.setProperty("name", "One");
user.createRelationshipTo(one, RelTypes.KNOWS);
Node first = graphDb.createNode();
first.setProperty("name", "First");
user.createRelationshipTo(first, RelTypes.KNOWS);
first.createRelationshipTo(one, RelTypes.KNOWS);
Node two = graphDb.createNode();
two.setProperty("name", "Two");
one.createRelationshipTo(two, RelTypes.KNOWS);
first.createRelationshipTo(two, RelTypes.KNOWS);
Node three = graphDb.createNode();
three.setProperty("name", "Three");
two.createRelationshipTo(three, RelTypes.KNOWS);
Node four = graphDb.createNode();
four.setProperty("name", "Four");
three.createRelationshipTo(four, RelTypes.CO_WORKER);
tx.success();
}
}
private void registerShutdownHook() {
Runtime.getRuntime().addShutdownHook(new Thread(graphDb::shutdown));
}
public void shutdown() {
graphDb.shutdown();
}
}