我在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兼容。
2条答案
按热度按时间dxpyg8gm1#
正如在this answer中提到的,COUNT子查询允许您利用非常高效的
getDegree
操作(通过避免任何DB命中)。如果来自
Foo
节点的所有HAS
关系都以Bar
节点结束,那么可以将第一个模式简化为(f)-[:HAS]->()
,以便在同一个查询中利用两次getDegree
操作:这个查询应该非常快。
neo4j 5.0之前
如果您使用的是5.0以上的neo4j版本,您应该能够将
COUNT { ... }
替换为SIZE(...)
以使用getDegree
操作。Here是关于这个的知识库文章。hjzp0vay2#
我看到的一个问题是,您首先在
WHERE NOT
上进行过滤。通常更有效的方法是找到你想要的,然后过滤掉。试试这个:
另外,
apoc.periodic.iterate
似乎不是这里的正确解决方案,因为您实际上并不希望以批处理的方式执行任何操作。该命令更适合设置属性。您可以通过在call
之后调用yield
来获得结果,但仅限于它所做的事情;详情请参见https://neo4j.com/labs/apoc/4.1/overview/apoc.periodic/apoc.periodic.iterate/的输出部分。