我正在使用Neo4j作为数据库来存储与另一个数据库对象有关的投票信息。
我有一个Vote对象,其中包含以下字段:
type:String
,其值为UP
或DOWN
。argId:String
是链接到唯一参数对象的字符串ID值我正在尝试使用以下查询来查询分配给给定argId的投票数:
MATCH (v:Vote) WHERE v.argId = '214' AND v.type='DOWN'
RETURN {downvotes: COUNT(v)} AS votes
UNION
MATCH (v:Vote) WHERE v.argId = '214' AND v.type='UP'
RETURN {upvotes: COUNT(v)} AS votes
请注意,以上密码-可以正常工作并返回预期结果:
[
{
"downvotes": 1
},
{
"upvotes": 10
}
]
但是我觉得查询可能会更整洁,并且想要编写如下内容:
MATCH (v:Vote) WHERE v.argId = '214' AND v.type='UP'
MATCH (b:Vote) WHERE b.argId = '214' AND b.type='DOWN'
RETURN {upvotes: COUNT(v), downvotes: COUNT(b)}
只要通读一下,我认为这是有道理的,b和v被声明为单独的变量,所以一切都应该很好(所以我认为)。
但是运行它给了我这个:
{
"upvotes": 10,
"downvotes": 10
}
但这应该是我上面的内容。
这是为什么?
我是neo4j和cypher的新手,所以我可能还不了解cypher的工作原理。
任何人都可以发光吗?
谢谢!
p.s。我正在使用Neo4j 3.5.6,并通过桌面网络浏览器应用程序运行查询。
答案 0 :(得分:0)
我认为,如果您运行此查询,则可以更清楚地了解正在发生的事情。您的查询产生upvotes(10)和downvotes(1)的笛卡尔积。该乘积是10行的结果集。随后计算它们时,每个都有十个。
MATCH (v:Vote) WHERE v.argId = '214' AND v.type='UP'
MATCH (b:Vote) WHERE b.argId = '214' AND b.type='DOWN'
RETURN v.type, b.type
要获得结果,您需要过滤值并分别进行计数。
有两个匹配语句,而不是两个match语句,它检索所有感兴趣的值,然后使用条件语句将它们过滤到upvotes和downbotes存储桶中。
类似的东西可能适合您。
MATCH (v:Vote {argId: '214'})
WHERE v.type IN ['UP', 'DOWN']
RETURN {
upvotes: count(CASE WHEN v.type = 'DOWN' THEN 1 END),
downvotes: count(CASE WHEN v.type = 'UP' THEN 1 END)
} AS vote_result
使用APOC,您可以执行类似的操作,即使用类型值本身来汇总计数,然后使用APOC将其转换为以类型为地图键的地图。
MATCH (v:Vote {argId: '214'})
WHERE v.type IN ['UP', 'DOWN']
WITH [v.type, count(*)] AS vote_pair
RETURN apoc.map.fromPairs(collect(vote_pair)) AS votes