IT序号网

neo4j遍历和图算法知识解答

flyfish 2021年06月14日 数据库 132 0

这篇blog主要和大家分享一下neo4j中是如何对节点进行遍历,和其中集成的图论的一些常用算法。

遍历

IT虾米网   这是neo4j官方的中文教程。

Java代码   收藏代码
  1. private static Traverser getFriends(Node node )  
  2. {  
  3.     TraversalDescription td = Traversal.description()  
  4.             .breadthFirst()  
  5.             .relationships( RelTypes.KNOWS, Direction.OUTGOING )  
  6.             .evaluator( Evaluators.excludeStartPosition() );  
  7.     return td.traverse( node );  
  8. }  
 TraversalDescription提供了用户遍历节点的方法,并且用户需要自己添加遍历的条件。
首先用户可以定义是使用深度优先还收广度优先 breadthFirst() 和 depthFirst();relationships定义了遍历取得节点的关系类型,是入度Direction.INCOMING还是出度Direction.OUTGOING还是both;evaluator用来定义筛选的条件,比如去掉开始节点,结束节点,遍历深度(toDepth(3))等,具体可以参照官方的API文档。
Java代码   收藏代码
  1. int num = 0;  
  2. String result = neoNode.getProperty( "name" ) + "'s friends:\n";  
  3. Traverser friendsTraverser = getFriends( neoNode );  
  4. for ( Path friendPath : friendsTraverser )  
  5. {  
  6.     output += "At depth " + friendPath.length() + " => "  
  7.               + friendPath.endNode()  
  8.                       .getProperty( "name" ) + "\n";  
  9.     numberOfFriends++;  
  10. }  
  11. output += "Number of friends found: " + numberOfFriends + "\n";  
  打印出结果
Java代码   收藏代码
  1. Thomas Anderson's friends:  
  2. At depth 1 => Trinity  
  3. At depth 1 => Morpheus  
  4. At depth 2 => Cypher  
  5. At depth 3 => Agent Smith  
  6. 找到朋友的数量: 4  
 下面介绍如何按照一个预先定义好的顺序遍历图。
创建一个数据库
Java代码   收藏代码
  1. Node A = db.createNode();  
  2. Node B = db.createNode();  
  3. Node C = db.createNode();  
  4. Node D = db.createNode();  
  5. A.createRelationshipTo( B, REL1 );  
  6. B.createRelationshipTo( C, REL2 );  
  7. C.createRelationshipTo( D, REL3 );  
  8. A.createRelationshipTo( C, REL2 );  
现在关系(REL1-->REL2-->REL), 当遍历的时候,Evaluator能够对它进行检验,确保只有该关系顺序的路径才会被包括。
Java代码   收藏代码
  1. ArrayList<RelationshipType> orderedPathContext = new ArrayList<RelationshipType>();  
  2. orderedPathContext.add( REL1 );  
  3. orderedPathContext.add( withName( "REL2" ) );  
  4. orderedPathContext.add( withName( "REL3" ) );  
  5. TraversalDescription td = Traversal.description()  
  6.         .evaluator( new Evaluator()  
  7.         {  
  8.             @Override  
  9.             public Evaluation evaluate( final Path path )  
  10.             {  
  11.                 if ( path.length() == 0 )  
  12.                 {  
  13.                     return Evaluation.EXCLUDE_AND_CONTINUE;  
  14.                 }  
  15.                 RelationshipType expectedType = orderedPathContext.get( path.length() - 1 );  
  16.                 boolean isExpectedType = path.lastRelationship()  
  17.                         .isType( expectedType );  
  18.                 boolean included = path.length() == orderedPathContext.size()  
  19.                                    && isExpectedType;  
  20.                 boolean continued = path.length() < orderedPathContext.size()  
  21.                                     && isExpectedType;  
  22.                 return Evaluation.of( included, continued );  
  23.             }  
  24.         } );  
 打印出结果
Java代码   收藏代码
  1. Traverser traverser = td.traverse( A );  
  2. PathPrinter pathPrinter = new PathPrinter( "name" );  
  3. for ( Path path : traverser )  
  4. {  
  5.     output += Traversal.pathToString( path, pathPrinter );  
  6. }  
 用户也可以通过自定义格式输出路径。
Java代码   收藏代码
  1. static class PathPrinter implements Traversal.PathDescriptor<Path>  
  2. {  
  3.     private final String nodePropertyKey;  
  4.    
  5.     public PathPrinter( String nodePropertyKey )  
  6.     {  
  7.         this.nodePropertyKey = nodePropertyKey;  
  8.     }  
  9.    
  10.     @Override  
  11.     public String nodeRepresentation( Path path, Node node )  
  12.     {  
  13.         return "(" + node.getProperty( nodePropertyKey, "" ) + ")";  
  14.     }  
  15.    
  16.     @Override  
  17.     public String relationshipRepresentation( Path path, Node from,  
  18.             Relationship relationship )  
  19.     {  
  20.         String prefix = "--", suffix = "--";  
  21.         if ( from.equals( relationship.getEndNode() ) )  
  22.         {  
  23.             prefix = "<--";  
  24.         }  
  25.         else  
  26.         {  
  27.             suffix = "-->";  
  28.         }  
  29.         return prefix + "[" + relationship.getType().name() + "]" + suffix;  
  30.     }  
  31. }  

 图算法

neo4j中集成了一些常用的图算法,包括最短路径,Dijkstra,A*算法。
最短路径
Java代码   收藏代码
  1. public Iterable<Path> findShortestPath(Node node1, Node node2) {  
  2.     PathFinder<Path> finder = GraphAlgoFactory.shortestPath(  
  3.         Traversal.expanderForTypes(RelTypes.KNOWS, Direction.BOTH), 10);  
  4.         Iterable<Path> paths = finder.findAllPaths(node1, node2);  
  5.     return paths;  
  6. }  
 
Java代码   收藏代码
  1. for(Path shortestPath: findShortestPath(aa, ab)) {    
  2.             System.out.println(shortestPath.toString());    
  3. }  
 Traversal.expanderForTypes用来定义遍历的深度和节点关系的出入度。
Dijkstra解决有向图中任意两个顶点之间的最短路径问题。
Java代码   收藏代码
  1. PathFinder<WeightedPath> finder = GraphAlgoFactory.dijkstra(  
  2.         Traversal.expanderForTypes( ExampleTypes.MY_TYPE, Direction.BOTH ), "cost" );  
  3.    
  4. WeightedPath path = finder.findSinglePath( nodeA, nodeB );  
  5. path.weight();  

  使用 A*算法是解决静态路网中求解最短路最有效的方法。

Java代码   收藏代码
  1. Node nodeA = createNode( "name""A""x", 0d, "y", 0d );  
  2. Node nodeB = createNode( "name""B""x", 7d, "y", 0d );  
  3. Node nodeC = createNode( "name""C""x", 2d, "y", 1d );  
  4. Relationship relAB = createRelationship( nodeA, nodeC, "length", 2d );  
  5. Relationship relBC = createRelationship( nodeC, nodeB, "length", 3d );  
  6. Relationship relAC = createRelationship( nodeA, nodeB, "length", 10d );  
  7.    
  8. EstimateEvaluator<Double> estimateEvaluator = new EstimateEvaluator<Double>()  
  9. {  
  10.     public Double getCost( final Node node, final Node goal )  
  11.     {  
  12.         double dx = (Double) node.getProperty( "x" ) - (Double) goal.getProperty( "x" );  
  13.         double dy = (Double) node.getProperty( "y" ) - (Double) goal.getProperty( "y" );  
  14.         double result = Math.sqrt( Math.pow( dx, 2 ) + Math.pow( dy, 2 ) );  
  15.         return result;  
  16.     }  
  17. };  
  18. PathFinder<WeightedPath> astar = GraphAlgoFactory.aStar(  
  19.         Traversal.expanderForAllTypes(),  
  20.         CommonEvaluators.doubleCostEvaluator( "length" ), estimateEvaluator );  
  21. WeightedPath path = astar.findSinglePath( nodeA, nodeB );  

 


发布评论
IT序号网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!

图数据库neo4j和关系数据库的区别知识解答
你是第一个吃螃蟹的人
发表评论

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。