我有一个存储在Neo4j中的大型网络。基于特定的根节点,我想提取该节点周围的子图并将其存储在其他地方。所以,我需要的是符合我的过滤条件的节点和边的集合。
Afaik没有开箱即用的解决方案。有一个graph matching component available,但它只适用于完美匹配。 Neo4j API本身仅定义了graph traversal,我可以用它来定义应该访问哪些节点/边缘:
Traverser exp = Traversal
.description()
.breadthFirst()
.evaluator(Evaluators.toDepth(2))
.traverse(root);
现在,我可以将所有节点/边添加到所有路径的集合中,但效率非常低。你会怎么做?谢谢!
编辑将每个遍历的最后一个节点和最后一个关系添加到子图中是否有意义?
答案 0 :(得分:3)
至于图匹配,它已被http://docs.neo4j.org/chunked/snapshot/cypher-query-lang.html取代,它很适合,并支持带有可选关系的模糊匹配。
对于子图表示,我会使用Cypher输出来构造新的Cypher语句来重新创建图形,就像SQL导出一样,
start n=node:node_auto_index(name='Neo')
match n-[r:KNOWS*]-m
return "create ({name:'"+m.name+"'});"
答案 1 :(得分:2)
我通过构建基于所有遍历端点的诱导子图来解决它。
从每个遍历的最后一个节点和边的集合构建子图不起作用,因为不包括不属于任何最短路径的边。
代码段如下所示:
Set<Node> nodes = new HashSet<Node>();
Set<Relationship> edges = new HashSet<Relationship>();
for (Node n : traverser.nodes())
{
nodes.add(n);
}
for (Node node : nodes)
{
for (Relationship rel : node.getRelationships())
{
if (nodes.contains(rel.getOtherNode(node)))
edges.add(rel);
}
}
每条边都加两次。一次用于传出节点,一次用于传入节点。使用Set,我可以确保它只在集合中一次。
可以仅迭代传入/传出边缘,但不清楚如何处理循环(从节点到自身的边缘)。它们属于哪个类别?此代码段没有此问题。
答案 2 :(得分:0)
请参阅dumping the database to cypher statements
dump START n=node({self}) MATCH p=(n)-[r:KNOWS*]->(m) RETURN n,r,m;
还有一个将第一个数据库(db1)的子图导入第二个(db2)的示例。