跟着官网代码学习.jpg–jdk 1.8.0 & neo4j 3.5
https://neo4j.com/docs/java-reference/current/java-embedded/
目标:查找朋友以及朋友的朋友 + 找最终的Hacker
- 待实现节点关系图:
1. 节点以及关系建立 实现代码:
1)matrixNodeID = matrix.getId();
matrixNodeI是一个private long变量->仅用于存放Node matrix的ID,不是每新建一个Node都要更新一下;
2)Relationship rel2 = morpheus.createRelationshipTo(cypher, RelTypes.KNOWS); rel.setProperty("disclosure","public");
给relationship添加属性的方法;
3)Relationship rel2 = morpheus.createRelationshipTo(cypher, RelTypes.KNOWS); rel.setProperty("disclosure","public");
给relationship添加属性的方法;
private void createNodespace() {
try (Transaction tx = graphDb.beginTx()) {
Node matrix = graphDb.createNode();
matrixNodeID = matrix.getId(); //matrixNodeID是一个private long变量->仅用于存放Node matrix的ID
Node thomas = graphDb.createNode();
thomas.setProperty("name", "Thomas Anderson");
thomas.setProperty("age", "29");
matrix.createRelationshipTo(thomas, RelTypes.NEO_NODE);
Node trinity = graphDb.createNode();
trinity.setProperty("name", "Trinity");
Relationship rel = thomas.createRelationshipTo(trinity, RelTypes.KNOWS);
rel.setProperty("age", "3 days");
Node morpheus = graphDb.createNode();
morpheus.setProperty("name", "Morpheus");
morpheus.setProperty("occupation", "Total badass");
morpheus.setProperty("rank", "Captain");
Relationship rel1 = morpheus.createRelationshipTo(trinity, RelTypes.KNOWS);
rel.setProperty("age", "12 years");
thomas.createRelationshipTo(morpheus, RelTypes.KNOWS);
Node cypher = graphDb.createNode();
cypher.setProperty("last name", "Reagan");
cypher.setProperty("name", "Cypher");
Relationship rel2 = morpheus.createRelationshipTo(cypher, RelTypes.KNOWS);
rel.setProperty("disclosure", "public");
Node smith = graphDb.createNode();
smith.setProperty("language", "C++");
smith.setProperty("name", "Agent Smith");
smith.setProperty("version", "1.0b");
Relationship rel3 = cypher.createRelationshipTo(smith, RelTypes.KNOWS);
rel3.setProperty("age", "6 months");
rel3.setProperty("disclosure", "secret");
Node architect = graphDb.createNode();
architect.setProperty("name", "The Architect");
smith.createRelationshipTo(architect, RelTypes.CODED_BY);
tx.success();
}
}
2. 找到朋友以及朋友的朋友 实现代码:
- 图的遍历:获取到与图中节点之间的关系相关的信息。进行遍历之前,需要对遍历的方式进行描述。描述信息由以下要素组成:
遍历的路径:通常用关系的类型和方向来表示;
遍历的顺序:深度优先depthFirst
& 广度优先breadthFirst
;
遍历的唯一性:可以指定在整个遍历中是否允许经过重复的节点、关系或路径;
遍历过程的决策器:用来在遍历过程中判断是否继续进行遍历,以及遍历过程的返回结果;
起始节点:遍历过程的起点。 - 遍历方式的描述信息由 org.neo4j.graphdb.traversal.TraversalDescription 接口来表示。通过 TraversalDescription 接口的方法可以描述上面介绍的遍历过程的不同要素。
- 注意要点:
1)matrixNodeID = matrix.getId();
matrixNodeI是一个private long变量->仅用于存放Node matrix的ID,不是每新建一个Node都要更新一下;
2)Traverser friendsTraverser = getFriends(neoNode);
Traverser类型:Implementing this interface allows an object to be the target of the “for-each loop” statement.
3)具体的遍历描述方法:通过Traverser类的description方法创建了一个默认的遍历描述对象,通过breadthFirst设置为广度优先的遍历方式,relationships方法设置遍历时经过的关系的类型;比较复杂的表示遍历过程决策器的evaluator方法,该方法的参数是org.neo4j.graphdb.traversal.Evaluator
接口的实现对象,Evaluator接口只有一个方法evaluate,evaluate方法的参数是Path接口的实现对象,表示当前的遍历路径,而evaluate方法的返回值是枚举类型org.neo4j.graphdb.traversal.Evaluation
,表示不同的处理策略。处理策略由两个方面组成:是否包含当前节点&是否继续进行遍历。Evaluator 接口的实现者需要根据遍历时的当前路径,做出相应的决策,返回适当的 Evaluation 类型的值。类org.neo4j.graphdb.traversal.Evaluators
提供了一些实用的方法来创建常用的 Evaluator 接口的实现对象。示例代码中使用了 Evaluators 类的一个方法Evaluators.excludeStartPosition()
,包含start节点;另一个方法Evaluators.pruneWhereLastRelationshipTypeIs
返回的 Evaluator 接口的实现对象会根据遍历路径的最后一个关系的类型来进行判断,如果关系类型满足给定的条件,则不再继续进行遍历。 - 感觉有点难以理解,其实就是设置个遍历方式+遍历经过的关系类型+evaluator(Evaluators.是否包含当前节点&是否继续进行遍历),返回的是Traverse类型。
private Traverser getFriends(final Node person) {
TraversalDescription td = graphDb.traversalDescription()
.breadthFirst()
.relationships(RelTypes.KNOWS, Direction.OUTGOING)
.evaluator(Evaluators.excludeStartPosition());
return td.traverse(person);
}
- 通过NodeID找节点:之前存过matrix的NodeID
matrixNodeID = matrix.getId();
,通过graphDb.getNodeById(NodeID)
找到matrix节点,再通过找关系类型的endNode来找到NeoNode。
private Node getNeoNode() {
return graphDb.getNodeById(matrixNodeID)
.getSingleRelationship(RelTypes.NEO_NODE, Direction.OUTGOING)
.getEndNode();
}
- 找朋友的朋友:起始节点neoNode和遍历friendsTraverser。
for (Path friendPath : friendsTraverser) {}
得到遍历中的Path路径,用path.endNode()找到节点,再.getProperty()得到节点的属性。 - String类型是可以+的
public String printNeoFriends() {
try ( Transaction tx = graphDb.beginTx()) {
Node neoNode = getNeoNode();
int numOfFriends = 0;
String output = neoNode.getProperty("name") + "'s friends:\n";
Traverser friendsTraverser = getFriends(neoNode);
for (Path friendPath : friendsTraverser) {
output += "At depth" + friendPath.length() + "=>"
+friendPath.endNode()
.getProperty("name") + "\n";
numOfFriends++;
}
output += "Number of friends found" + numOfFriends + "\n";
return output;
}
}
3. 找最终的Hacker 实现代码:
- 示例代码中使用了 Evaluators 类的一个方法
Evaluators.excludeStartPosition()
,包含start节点;另一个方法Evaluators.pruneWhereLastRelationshipTypeIs
返回的 Evaluator 接口的实现对象会根据遍历路径的最后一个关系的类型来进行判断,如果关系类型满足给定的条件,则不再继续进行遍历。
public String printMatrixHackers() {
try (Transaction tx = graphDb.beginTx()) {
String output = "Hackers:\n";
int numOfHackers = 0;
Traverser traverser = findHackers(getNeoNode());
for(Path hackerPath : traverser) {
output += "At depth " + hackerPath.length() + "=>"
+ hackerPath.endNode()
.getProperty("name") + "\n";
numOfHackers++;
}
output += "Number of hackers found: " + numOfHackers + "\n";
return output;
}
}
private Traverser findHackers(final Node startNode) {
TraversalDescription td = graphDb.traversalDescription()
.breadthFirst()
.relationships(RelTypes.CODED_BY, Direction.OUTGOING)
.relationships(RelTypes.KNOWS, Direction.OUTGOING)
.evaluator(Evaluators
.includeWhereLastRelationshipTypeIs(RelTypes.CODED_BY));
return td.traverse(startNode);
}
4. 具体代码: https://github.com/Amy996bbq/Neo4j/blob/master/learn/NewMatrix_1.java