我正在尝试使用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。嗯,明显的原因是递归的深度变得太大了。 但是我的代码可能有问题吗?
答案 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秒。