用密码查询A和B之间不经过C的最短路径,这不是很慢吗?或推荐Cypher/Neo4j的替代品
我正在处理一个有数千个节点的图。假设我有个人节点,以及它们之间的朋友关系。e、 g.,格斯-[:朋友]-skylar 如果我想在hank和gus之间找到最短的朋友路径,只要他们之间的距离不超过20个rel,我可以这样做:用密码查询A和B之间不经过C的最短路径,这不是很慢吗?或推荐Cypher/Neo4j的替代品,neo4j,cypher,shortest-path,Neo4j,Cypher,Shortest Path,我正在处理一个有数千个节点的图。假设我有个人节点,以及它们之间的朋友关系。e、 g.,格斯-[:朋友]-skylar 如果我想在hank和gus之间找到最短的朋友路径,只要他们之间的距离不超过20个rel,我可以这样做: START hank=node(68), gus=node(66) MATCH p = shortestPath((hank)-[:FRIENDS*..20]-(gus)) RETURN p 即使找到的最短路径长度为10或更长,这种方法仍然有效且快速 但是说我想找到一条从
START hank=node(68), gus=node(66)
MATCH p = shortestPath((hank)-[:FRIENDS*..20]-(gus))
RETURN p
即使找到的最短路径长度为10或更长,这种方法仍然有效且快速
但是说我想找到一条从汉克到格斯的路,不经过格伦
我尝试过的查询是:
START hank=node(68), gus=node(66), glenn=node(59)
MATCH p =(hank)-[:FRIENDS*..20]-(gus)
WHERE NOT glenn IN nodes(p)
RETURN p
ORDER BY length(p)
LIMIT 1;
这适用于30人左右的非常小的图,但如果有1000人,JVM就会耗尽heapspace
我猜Cypher会找到gus和hank之间长度小于等于20的所有路径,然后应用WHERE过滤器?很明显,这会很慢
从抽象意义上讲,这个算法应该在相同的big O运行时可行,因为所有的变化都是在搜索时检查以确保每个节点不是您想要避免的节点
对如何实现这一点有什么建议吗?我对塞弗很陌生
如果Cypher无法实现这一点,您可以推荐其他数据库和图形语言堆栈吗
谢谢您能测试以下查询的性能吗?主要区别在于它比较的是路径而不是节点。我还在路径中添加了一个方向,这将加快查询速度
START hank=node(68), gus=node(66), glenn=node(59)
MATCH p = allshortestPaths((hank)-[:FRIENDS]->(gus))
WITH COLLECT(p) AS gusPaths, hank, glenn
MATCH p2 = allshortestPaths((hank)-[:FRIENDS]->(glenn))
WITH COLLECT(p2) AS glennPaths, gusPaths
WITH filter(x IN gusPaths
WHERE NONE (x2 IN glennPaths
WHERE x = x2)) AS filtered
RETURN filtered
ORDER BY length(filtered)
LIMIT 1
后面还有一个AllShortPaths关键字“s”。这对性能有何影响?对于Neo4j,我建议使用Traversal Framework API。Cypher是建立在这个基础上的,所以它可以让你更好地控制数据库的搜索方式。你能在路径上使用lambda过滤器吗?hank-[:FRIEDS*bfs e,v | v.name!='glenn']-gus参见示例6,这里没有返回任何结果,不过非常感谢您的建议。allshortestPaths仍然只查找长度尽可能短的路径。由于我对Cypher不太熟悉,我无法从你的建议中判断你是否知道当我说从A到B的最短路径不经过C时,我不要求它像从A到B的绝对最短路径那样短,它可能经过也可能不经过C。它可能需要更长的时间才能避开C。我开始认为Cypher可能不支持这一点。