Cypher如何返回节点总数以及有限的节点集合?

10

在一个cypher查询中,是否有可能提取有限的节点集和节点总数?

match (n:Molecule) with n, count(*) as nb limit 10 return {N: nb, nodes: collect(n)}

上述查询正确返回了节点,但将节点数作为1返回。我当然知道为什么会返回1,因为没有分组,但是不知道如何进行更正。


能否将此与where语句结合起来?基本上,我不想要总节点数。我想要满足“某些”条件的节点计数。 - canbax
3个回答

9
以下查询返回了整个行数的计数器(我猜这就是所需的内容)。然后它再次匹配并限制您的搜索,但原始计数器仍然可用,因为它通过WITH语句传递。
MATCH 
    (n:Molecule)
WITH 
    count(*) AS cnt
MATCH 
    (n:Molecule)
WITH 
    n, cnt LIMIT 10
RETURN 
    { N: cnt, nodes:collect(n) } AS molecules

6
如果匹配过程很复杂,那么复制它会导致性能下降吗?还是Neo4j足够聪明以便重用第一次匹配的结果? - Szczepan Hołyszewski
1
刚刚使用了一个非常复杂的查询进行了测试。不,Neo4j并不够聪明。没有包括 count 的部分时,需要 44-45 秒,包含 count 后需要 89-90 秒。就像要运行两次查询一样,所以其实并没有必要将这些查询组合起来...@SzczepanHołyszewski - gurel_kaynak

3

以下是另一种解决方案:

match (n:Molecule) return {nodes: collect(n)[0..5], n: length(collect(n))}

30,000个节点,84毫秒。这比由Wassgren提出的上述方法更短,但不如效率高。


它可能比之前的解决方案占用更多的内存。我们在这里讨论的是数百万个分子节点,其中包含了分子描述(SMILES字符串、INCHI密钥、分子PNG的base64转换)。 - Pierre
为什么你的解决方案需要更多的内存?我不理解。我们只返回了一个很小的结果子集。是因为collect语句吗? - canbax
我指的是使用collect函数的解决方案,我怀疑它会在内存中加载已收集的节点,如果是这样,那么集合将包含所有标记为Molecule的节点......数量可能有几百万。 - Pierre
谢谢。也许Neo4j会在“收集”之前对索引语句进行优化。此外,我认为你的答案值得成为答案。以前的答案只会使复杂度变得更糟。他们只是串行地执行了2个查询。与此不同的是,他们可以并行执行2个查询。 - canbax
我尝试使用这个查询来处理一个相对较大的节点集(290万个节点)。我使用了类似于 OPTIONAL MATCH (x:Card) WHERE ( (TRUE) ) RETURN ID(x), x SKIP 0 LIMIT 10 的查询来从这290万张卡片中获取10张卡片。它的执行时间只有1到2毫秒。但是当我尝试使用 OPTIONAL MATCH (x:Card) WHERE ( (TRUE) ) RETURN collect(ID(x))[0..10], collect(x)[0..10], length(collect(x)) 时,第一次执行需要4500毫秒。在第二次运行时,它执行了2700毫秒。虽然看起来不太糟糕,但肯定比前者慢。 - canbax

0
这个解决方案将工作分为两个部分:首先获取完整的行列表,使用WITH对其进行计数并将其收集到一个列表中,然后使用collect()进行分页的子查询。如果您需要在结果中带入关于行的其他信息,请将其放在"WITH item"和"RETURN collect(item)"之间,这样只会对返回页面上的项目执行该操作。
MATCH (n:MyLabel)
WITH collect(n) as collection,count(n) as cnt 
CALL{
    WITH collection
    UNWIND collection as item
    WITH item ORDER BY item.id DESC SKIP 10 LIMIT 5
    RETURN collect(item) as items
}
RETURN cnt, items

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接