neo4j 如何批量处理数百万个节点并将结果保存到文件中

ttisahbt  于 2023-05-28  发布在  其他
关注(0)|答案(2)|浏览(247)

我在Neo4j中有以下模式:

(:Foo)-[:HAS]->(:Bar)
(:Foo)<-[:IN]-(:Baz)

有数千万个(:Foo)(:Foo)(:Baz)之间可能有数百万个关系。
我想得到最大的(:Foo)(根据(:Foo)(:Baz)之间的许多关系),它与(:Bar)没有任何关系。
我试着:

MATCH (f:Foo) WHERE NOT (f)-[:HAS]->(:Bar)
WITH f, count([(f)<-[:IN]-()]) as b_count WHERE b_count > 10 RETURN f, b_count

但该查询永远不会结束。
我也试过使用apoc.periodic.iterate,但我不知道如何得到的结果。

CALL apoc.periodic.iterate(
"MATCH (f:Foo) WHERE NOT (f)-[:HAS]->(:Bar) RETURN f", 
"WITH f, count([(f)<-[:IN]-()]) as b_count WHERE b_count > 10 RETURN f, b_count",
 {parallel:true, batchSize:1000})

理想情况下,我希望得到按b_count排序的结果,并只返回最大的N
对所有结果进行排序以只得到最大的N可能对内存要求过高。如果可以将结果保存到一个文件中,我可以使用sort来对结果进行排序。
编辑:
如果可能,查询应该与neo4j 3.5兼容。

dxpyg8gm

dxpyg8gm1#

正如在this answer中提到的,COUNT子查询允许您利用非常高效的getDegree操作(通过避免任何DB命中)。
如果来自Foo节点的所有HAS关系都以Bar节点结束,那么可以将第一个模式简化为(f)-[:HAS]->(),以便在同一个查询中利用两次getDegree操作:

MATCH (f:Foo)
WHERE COUNT { (f)-[:HAS]->() } = 0
WITH f, COUNT { (f)<-[:IN]-() } AS b_count
WHERE b_count > 10
RETURN f, b_count

这个查询应该非常快。

neo4j 5.0之前

如果您使用的是5.0以上的neo4j版本,您应该能够将COUNT { ... }替换为SIZE(...)以使用getDegree操作。Here是关于这个的知识库文章。

hjzp0vay

hjzp0vay2#

我看到的一个问题是,您首先在WHERE NOT上进行过滤。通常更有效的方法是找到你想要的,然后过滤掉。
试试这个:

match (f:Foo)<-[r:IN]->(:Bar)
where not (f)-[:HAS]->(:Baz)
with f, count(r) as count_b
order by count(r) desc
return f, count_b
limit N

另外,apoc.periodic.iterate似乎不是这里的正确解决方案,因为您实际上并不希望以批处理的方式执行任何操作。该命令更适合设置属性。您可以通过在call之后调用yield来获得结果,但仅限于它所做的事情;详情请参见https://neo4j.com/labs/apoc/4.1/overview/apoc.periodic/apoc.periodic.iterate/的输出部分。

相关问题