CYPHER - 不同的COUNT返回相同的结果

时间:2016-10-02 13:05:52

标签: neo4j count cypher

我正在尝试使用以下查询计算两个计数之间的差异。

MATCH (user: User {username : 'bar' })
MATCH (user)-[upvote : UPVOTED]->(:Post)
MATCH (user)-[downvote : DOWNVOTED]->(:Post)
RETURN COUNT(upvote) - COUNT(downvote)

它始终返回0,因为两个计数值都相同。我已经为每个计数单独运行查询,它们确实不同(3和1)但是查询一起返回了无效的结果。

[UPDATE]

奇怪的是,当我运行此查询时

MATCH (user : User {username : 'bar' })
MATCH (user)-[upvote : UPVOTED]->(:Post)
MATCH (user)-[downvote : DOWNVOTED]->(:Post)
RETURN COUNT(downvote)

它返回3,而预期输出为1.就好像较大的MATCH支配结果

有什么想法吗?感谢

1 个答案:

答案 0 :(得分:4)

在执行MATCH和OPTIONAL MATCHES时,Neo4j会构建行。它们将取决于先前查询的结果数量。

例如,让我们说用户已经投票3投了1但是投了1。

在MATCH for upvotes的末尾,正在构建的行数为3,每个行都包含用户,以及每个upvoted关系。

但是在MATCH for downvotes的末尾,正在构建的行数为3.每行包含:用户,一个upvotes和一个downvote:

user, up1, down1 
user, up2, down1 
user, up3, down1

ups的数量应该是准确的,但是下降的数量也将是3。

请注意,这也是一个性能损失:您的查询以获取用户的downvotes并不像您期望的那样为单个用户运行一次,而是为用户的每一行一次运行一次(它恰好是每一行中的同一用户。)

如果您有2个downvotes而不是1个,那么将会有6行(3 x 2,每个upvote与每个可能的downvote配对):

user, up1, down1
user, up1, down2
user, up2, down1
user, up2, down2
user, up3, down1
user, up3, down2

如果你在查询结束时计算了DISTINCT ups和DISTINCT,你应该得到正确的数字,但更好的方法是注意背对背的匹配(第一场比赛导致更多而不是一行)并尽早计算计数:

MATCH (user : User {username : 'bar' })
MATCH (user)-[upvote : UPVOTED]->(:Post)
WITH user, COUNT(upvote) as upvotes
MATCH (user)-[downvote : DOWNVOTED]->(:Post)
RETURN upvotes, COUNT(downvote) as downvotes

这样做的原因是在中间的WITH之后,你只有1个构建的行:用户,具有upvote计数。当我们在downvotes上匹配时,构建的行将是具有每个downvote关系的upvote计数的用户:downvotes的数量x 1,当您运行COUNT函数时,它将为您提供准确的计数:

user, 3 as upvotes, down1

如果你有两个downvotes而不是一个,那就是:

user, 3 as upvotes, down1
user, 3 as upvotes, down2

等等。

一般情况下,当你可以的时候,在背对背比赛或可选比赛之间而不是在比赛结束时运行你的聚合(计数,收集等)(除非你当然知道你正在做什么和那个背对背的比赛对你的情况是正确的)。可视化neo4j如何构建您的行,这将为您提供可能出错的信息。