查找不在特定模式中的节点数[Neo4j]

时间:2018-09-13 16:48:01

标签: neo4j cypher runtime procedure

我想找到所有与其他用户节点没有中间连接的用户节点。

基本图形如下:

(User)-[]->(id)

其中一个用户节点可以具有多个ID,而某些Id具有多个用户节点。有一种特殊的兴趣模式

Match (u:User)-[]->(id)<-[]-(u2:User) 
where u <> u2 AND id(u) < id(u2) 
return u, id, u2

我想找到所有不在此模式下的用户。也就是说,找到与另一个用户没有连接的不同数量的用户。我在一台244 RAM大型计算机上,但是我尝试的所有操作都只是扼杀了Web界面上的连接。该图总共包含755MM用户和2B节点+。

这是他们查询中断的地方

Match (u:User)
Where not ((u)-[]->()<-[]-(:User)
RETURN count(distinct User)

如果可行,我将采取任何解决方案,包括APOC。 enter image description here

1 个答案:

答案 0 :(得分:0)

当前查询的主要问题是扩展正在杀死您。根据解释,平均而言,每个用户都连接到大约2个ID。因此Neo4j需要将其用于已保存行的内存增加四倍(中间表中的X2 #OfRows和X2 #OfColumnsPerRow可以过滤连接到另一个用户之前)(免责声明:Cypher不保证此行为,这是可能的可能发生的计划)

因此,您希望以某种方式设计查询,以最大程度地减少Neo4j触摸以获得正确结果所需的节点数量。在您的情况下,您的查询等同于询问有多少个用户没有ID,或者连接到该用户专有的ID? (由于这两个条件是互斥的,因此我们不必担心重叠)

假设id节点具有标签:ID ...

MATCH (id:ID)
WHERE SIZE((:User)-->(id))=1
WITH COUNT(id) as count
MATCH (u:User)
WHERE NOT (u)-->(:ID)
RETURN count+COUNT(u) as count

请注意,边缘和标签是在内部建立索引的,因此通过这种方式,Neo4j不需要实际扩展任何内容。只需按标签扫描即可获取节点,然后扫描边缘表以获取边缘数(并在需要时检查连接节点上的标签。Cypher无法保证此行为)


取决于模式发生的频率,另一种可行的方法是找到模式中的节点,然后从总数中减去。哪种方法更有效取决于模式发生与不发生的频率。

MATCH (id:ID)
WHERE SIZE((id)<--(:User)) > 1
MATCH (id)<--(u:User)
RETURN COUNT((:User))-COUNT(DISTINCT u) as count

您的另一个问题是可能需要计算的节点剪切量,具体取决于服务器上正在运行的内容以及分配给Neo4j的内容,这可能会超出Cypher(apoc有东西,但我没有找到任何用于模式计数的东西。解决此问题的一种方法是分页结果(使用LIMIT和OFFSET),然后以编程方式查询每页的计数并将其相加(根据更新频率,出错的可能性很小,但比什么都没有