在大型Neo4J数据库中查找特定长度的路径:内存性能

时间:2015-12-26 19:20:45

标签: python graph neo4j spatial neo4j-spatial

我有一个运行Neo4J Spatial插件的Neo4J实例。在其中,我有一个大约3.5 k节点的图表,每个节点都有相同的标签,我们称之为Basket。每个篮子与同一城市的物理位置有关,这些篮子的密度变化很大。我计算了每个篮子和600m内所有邻居之间的步行时间,并将它们存储为节点之间的非空间(定向)关系。因此,一些篮子似乎是大群集的一部分,而其他篮子几乎独立存在,与其他篮子只有一个或几乎没有关系。

我的用户遇到了一个问题:他们希望在一个地方开始,然后在另一个地方结束,一路上访问任意的,用户定义的篮子数量。我的程序旨在为用户提供一些路径选项(作为一系列节点 - 我将稍后对实际的行走方式进行排序),计算第n个最短路径。

我已经写了一个密码查询来执行此操作,如下所示。

start a = node(5955), b=node(6497) 
WITH a,b 
    MATCH p=((a)-[r:IS_WALKABLE_TO*4..5]->(b)) 
RETURN p

NB - 节点59556497是我选择的相距2英里的两个节点,在这种情况下,我决定选择4到5个篮子

但是,我一直遇到内存不足的异常,因此想要了解如何减少此问题的内存需求,使其在1到6秒的可接受时间内在价格合理的服务器上运行。

我的理解是,Neo4j不会执行笛卡尔积来找到解决方案,而是“选择每个节点并从每个节点嗅探,直到找到合适大小的连接”(请原谅我的措辞!),所以我对堆内存错误感到困惑。

我对改进计划的想法是:

  1. 以某种方式将查询的路径查找部分限制到边界框内的节点,由放置起始节点和结束节点确定(即,在每个方向上添加500米,然后将查询限制到这些节点)。但是,我找不到任何关于如何执行此操作的文档 - 是否可以不必为每个查询创建另一个空间层?

  2. 以不会造成内存错误的方式重写查询 - 这是否可以轻松实现?

  3. 完全停止使用Neo4J并编写算法,使用其他语言手动完成。如果是这样,你会推荐什么语言? C? C ++ / C#?或者我可以坚持使用Python / Ruby / Java / Go吗? (或者,我甚至认为我可以用PHP非常有效地完成它,但我不确定这是否是一个疯狂的时刻)。

  4. 关于如何解决这个问题的任何帮助和建议都很受欢迎!

2 个答案:

答案 0 :(得分:1)

您可能最好将此Cypher查询重构为Java代码unmanaged extension。然后,您的Java代码可以使用Traversal API或GraphAlgoFactory.pathsWithLength()

答案 1 :(得分:1)

我认为由于图形密集连接的形状,由于重复的中间节点,很容易导致数亿条可能的路径。

您应该在查询中添加LIMIT 100,然后停止搜索路径。

另一个想法是重写您的查询,首先找到a周围的不同起点(可能b)。

start a = node(5955), b=node(6497) 
MATCH (a)-[:IS_WALKABLE_TO]->(a1)-[:IS_WALKABLE_TO]->(a2)
WITH a, b, a2, collect(a1) as first
MATCH p = shortestPath((a2)-[:IS_WALKABLE_TO*..2]->(b)) 
RETURN count(*)

// or
UNWIND first as a1
RETURN [a,a1] + nodes(p) as path