neo4j遍历和图算法

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

遍历

http://docs.neo4j.org.cn/tutorials-java-embedded-traversal.html   这是neo4j官方的中文教程。

 

private static Traverser getFriends(Node node )
{
    TraversalDescription td = Traversal.description()
            .breadthFirst()
            .relationships( RelTypes.KNOWS, Direction.OUTGOING )
            .evaluator( Evaluators.excludeStartPosition() );
    return td.traverse( node );
}
 TraversalDescription提供了用户遍历节点的方法,并且用户需要自己添加遍历的条件。
首先用户可以定义是使用深度优先还收广度优先 breadthFirst() 和 depthFirst();relationships定义了遍历取得节点的关系类型,是入度Direction.INCOMING还是出度Direction.OUTGOING还是both;evaluator用来定义筛选的条件,比如去掉开始节点,结束节点,遍历深度(toDepth(3))等,具体可以参照官方的API文档。
int num = 0;
String result = neoNode.getProperty( "name" ) + "'s friends:\n";
Traverser friendsTraverser = getFriends( neoNode );
for ( Path friendPath : friendsTraverser )
{
    output += "At depth " + friendPath.length() + " => "
              + friendPath.endNode()
                      .getProperty( "name" ) + "\n";
    numberOfFriends++;
}
output += "Number of friends found: " + numberOfFriends + "\n";
  打印出结果
Thomas Anderson's friends:
At depth 1 => Trinity
At depth 1 => Morpheus
At depth 2 => Cypher
At depth 3 => Agent Smith
找到朋友的数量: 4
 下面介绍如何按照一个预先定义好的顺序遍历图。
创建一个数据库
Node A = db.createNode();
Node B = db.createNode();
Node C = db.createNode();
Node D = db.createNode();
A.createRelationshipTo( B, REL1 );
B.createRelationshipTo( C, REL2 );
C.createRelationshipTo( D, REL3 );
A.createRelationshipTo( C, REL2 );
现在关系(REL1-->REL2-->REL), 当遍历的时候,Evaluator能够对它进行检验,确保只有该关系顺序的路径才会被包括。
ArrayList<RelationshipType> orderedPathContext = new ArrayList<RelationshipType>();
orderedPathContext.add( REL1 );
orderedPathContext.add( withName( "REL2" ) );
orderedPathContext.add( withName( "REL3" ) );
TraversalDescription td = Traversal.description()
        .evaluator( new Evaluator()
        {
            @Override
            public Evaluation evaluate( final Path path )
            {
                if ( path.length() == 0 )
                {
                    return Evaluation.EXCLUDE_AND_CONTINUE;
                }
                RelationshipType expectedType = orderedPathContext.get( path.length() - 1 );
                boolean isExpectedType = path.lastRelationship()
                        .isType( expectedType );
                boolean included = path.length() == orderedPathContext.size()
                                   && isExpectedType;
                boolean continued = path.length() < orderedPathContext.size()
                                    && isExpectedType;
                return Evaluation.of( included, continued );
            }
        } );
 打印出结果
Traverser traverser = td.traverse( A );
PathPrinter pathPrinter = new PathPrinter( "name" );
for ( Path path : traverser )
{
    output += Traversal.pathToString( path, pathPrinter );
}
 用户也可以通过自定义格式输出路径。
static class PathPrinter implements Traversal.PathDescriptor<Path>
{
    private final String nodePropertyKey;
 
    public PathPrinter( String nodePropertyKey )
    {
        this.nodePropertyKey = nodePropertyKey;
    }
 
    @Override
    public String nodeRepresentation( Path path, Node node )
    {
        return "(" + node.getProperty( nodePropertyKey, "" ) + ")";
    }
 
    @Override
    public String relationshipRepresentation( Path path, Node from,
            Relationship relationship )
    {
        String prefix = "--", suffix = "--";
        if ( from.equals( relationship.getEndNode() ) )
        {
            prefix = "<--";
        }
        else
        {
            suffix = "-->";
        }
        return prefix + "[" + relationship.getType().name() + "]" + suffix;
    }
}
 图算法
neo4j中集成了一些常用的图算法,包括最短路径,Dijkstra,A*算法。
最短路径
public Iterable<Path> findShortestPath(Node node1, Node node2) {
	PathFinder<Path> finder = GraphAlgoFactory.shortestPath(
		Traversal.expanderForTypes(RelTypes.KNOWS, Direction.BOTH), 10);
		Iterable<Path> paths = finder.findAllPaths(node1, node2);
	return paths;
}
 
for(Path shortestPath: findShortestPath(aa, ab)) {  
            System.out.println(shortestPath.toString());  
}
 Traversal.expanderForTypes用来定义遍历的深度和节点关系的出入度。
Dijkstra解决有向图中任意两个顶点之间的最短路径问题。
PathFinder<WeightedPath> finder = GraphAlgoFactory.dijkstra(
        Traversal.expanderForTypes( ExampleTypes.MY_TYPE, Direction.BOTH ), "cost" );
 
WeightedPath path = finder.findSinglePath( nodeA, nodeB );
path.weight();
  使用 A*算法是解决静态路网中求解最短路最有效的方法。
Node nodeA = createNode( "name", "A", "x", 0d, "y", 0d );
Node nodeB = createNode( "name", "B", "x", 7d, "y", 0d );
Node nodeC = createNode( "name", "C", "x", 2d, "y", 1d );
Relationship relAB = createRelationship( nodeA, nodeC, "length", 2d );
Relationship relBC = createRelationship( nodeC, nodeB, "length", 3d );
Relationship relAC = createRelationship( nodeA, nodeB, "length", 10d );
 
EstimateEvaluator<Double> estimateEvaluator = new EstimateEvaluator<Double>()
{
    public Double getCost( final Node node, final Node goal )
    {
        double dx = (Double) node.getProperty( "x" ) - (Double) goal.getProperty( "x" );
        double dy = (Double) node.getProperty( "y" ) - (Double) goal.getProperty( "y" );
        double result = Math.sqrt( Math.pow( dx, 2 ) + Math.pow( dy, 2 ) );
        return result;
    }
};
PathFinder<WeightedPath> astar = GraphAlgoFactory.aStar(
        Traversal.expanderForAllTypes(),
        CommonEvaluators.doubleCostEvaluator( "length" ), estimateEvaluator );
WeightedPath path = astar.findSinglePath( nodeA, nodeB );
 

你可能感兴趣的:(neo4j)