使用neo4j搜索强连接组件

时间:2013-08-07 19:34:27

标签: java algorithm neo4j

我正在尝试使用neo4j来实现SCC算法来存储图形。

这是我对DFS的实现:

void dfs(GraphDatabaseService g, Node node, long counter) {

    Transaction tx = g.beginTx();
    node.setProperty("explored", true);
    tx.success();
    tx.finish();
    System.out.println("Exporing node " + node.getProperty("name") + "with depth " + counter);

    Iterator<Relationship> it = node.getRelationships(Direction.OUTGOING, RelTypes.KNOWS).iterator();
    while (it.hasNext()) {
        Node end = it.next().getEndNode();
        if (!(boolean) end.getProperty("explored"))
            dfs(g, end, ++counter);
    }  
}

抛出StackOverflowError。嗯,明显的原因是递归的深度变得太大了。 但是我的代码可能有问题吗?

1 个答案:

答案 0 :(得分:4)

没有必要编写自己的递归DFS,因为Neo4j提供了开箱即用的功能。我会以下列方式重写你的方法:

void dfs(GraphDatabaseService g, Node node) {

    //neo4j provided traversal API
    TraversalDescription traversalDescription = new TraversalDescriptionImpl()
            .depthFirst()
            .relationships(RelTypes.KNOWS, Direction.OUTGOING)
            .uniqueness(Uniqueness.NODE_GLOBAL);

    Iterable<Node> nodesInComponent = traversalDescription.traverse(node).nodes();

    //uses GraphAware to save some lines of code
    new IterableInputBatchTransactionExecutor<>(g, 1000, nodesInComponent, new UnitOfWork<Node>() {
        @Override
        public void execute(GraphDatabaseService database, Node input) {
            System.out.println("Exploring node " + input.getProperty("name"));
            if (!(boolean) input.getProperty("explored", false)) {
                input.setProperty("explored", true);
            }
        }
    }).execute();
}

前四行使用纯Neo4j API并检索一个惰性迭代,它可以为您提供所需的节点。

由于性能原因,其余行以1000个批次而不是单独的事务编写“已探索”属性。对于brewity,使用GraphAware框架(免责声明:我是它的作者),但它可以用更多的纯Neo4j代码编写。

我尝试了10,000个节点(一个连接的组件),花了大约26秒。