问题描述
我有一个组成DAG(有向无环图)的节点的集合,没有保证任何循环。我想将节点存储在数据库中,并让数据库执行搜索,向我显示两个节点之间的所有路径。
每个节点都可以用具有以下内容的JSON对象来描述:
{'id':'id','outbound':['id1','id2','id3']}
}
所以如果我在数据库中有这些节点:
{'id':'id0','id2']}
}
{'id':'id1','outbound':['id2','id3','id4','id5,'id6']}
}
{'id':'id2','id3'}
}
如果我想知道连接id0
和id3
的所有路径,我想得到三个列表:
id0 -> id1 -> id3
id0 -> id2 -> id3
id0 -> id1 -> id2 -> id3
我今天有数千个这样的节点,明天我将有成千上万个。但是,数据库中有很多 DAG,典型的DAG只有5-10个节点,因此这个问题很容易解决。
我相信没有办法有效地执行MysqL(目前所有对象都存储在JSON列的表中),但是我相信可以在像Neo4j这样的图形数据库中有效地做到这一点
我看过有关路径查找算法的Neo4J文档,也许我很困惑,但是这些示例看上去并不像实际的示例。我发现一个MySQL example使用存储过程,并且看起来并不能很好地并行化。我什至不知道Amazon Neptune在做什么;我认为它使用的是Spark GraphX。
我对从哪里开始感到迷茫。
解决方法
与Neo4j完全兼容。
导入json数据
[
{"id":"id0","outbound":["id1","id2"]
},{"id":"id1","outbound":["id2","id3","id4","id5","id6"]
},{"id":"id2","id3"]
}
]
CALL apoc.load.json("graph.json")
YIELD value
MERGE (n:Node {id: value.id})
WITH n,value.outbound AS outbound
UNWIND outbound AS o
MERGE (n2:Node {id: o})
MERGE (n)-[:Edge]->(n2)
您提供的数据显然不是非循环的...
获取两个节点之间的所有路径
由于您没有提及最短路径,而是所有路径,因此不需要特定的算法:
MATCH p=(:Node {id: "id0"})-[:Edge*]->(:Node {id: "id3"}) RETURN nodes(p)
"[{""id"":id0},{""id"":id1},{""id"":id3}]"
"[{""id"":id0},{""id"":id2},{""id"":id3}]"
与MySql进行比较
请参见how-much-faster-is-a-graph-database-really
,图数据科学库寻径算法旨在查找最短的加权路径,并使用与Dijkstra类似的算法来查找它们。在您的情况下,您似乎正在处理有向未加权图,可以使用本机密码allShortestPath
过程:
一个例子是:
MATCH (n1:Node{id:"A"}),(n2:Node{id:"B"})
MATCH path=allShortestPaths((n1)-[*..10]->(n2))
RETURN [n in nodes(path) | n.id] as outbound_nodes_id
检查Cypher refcard以查看Neo4j中Cypher可用的内容总是有用的