Neo4j 返回一个匹配语句的多个关系计数

Neo4j 返回一个匹配语句的多个关系计数,neo4j,cypher,Neo4j,Cypher,我想这样做: MATCH(p:person)-[a:UPVOTED]->(t:topic),(p:person)-[b:dowvoted]->(t:topic),(p:person)-[c:FLAGGED]->(t:topic),其中ID(t)=4返回计数(a)、计数(b)、计数(c) …但是当我应该得到2,1,1时,我得到了所有的0计数。让我们从重构查询开始(希望它的意义不会丢失): 因为t是您的主要变量(因为您正在对其进行筛选),所以我将标签匹配了一次,然后在其余的匹配中仅使用该变量。看到查

我想这样做:

MATCH(p:person)-[a:UPVOTED]->(t:topic),(p:person)-[b:dowvoted]->(t:topic),(p:person)-[c:FLAGGED]->(t:topic),其中ID(t)=4返回计数(a)、计数(b)、计数(c)


…但是当我应该得到2,1,1时,我得到了所有的0计数。让我们从重构查询开始(希望它的意义不会丢失):

因为
t
是您的主要变量(因为您正在对其进行筛选),所以我将标签匹配了一次,然后在其余的匹配中仅使用该变量。看到查询像这样被清理,在我看来,您试图计算某个主题的所有得票/反对票/标志,但您不在乎是谁做了这些事情。目前,由于您使用的是同一个变量
p
Cypher将尝试为所有三行匹配同一个人。所以你可以有不同的变量:

 (p1:person)-[upvote:UPVOTED]-(t),
 (p2:person)-[downvote:DOWNVOTED]->(t),
 (p3:person)-[flag:FLAGGED]->(t)
或者更好,因为您没有在其他任何地方引用人员,所以您可以忽略变量:

(:person)-[upvote:UPVOTED]-(t),
(:person)-[downvote:DOWNVOTED]->(t),
(:person)-[flag:FLAGGED]->(t)
从风格上来说,我还建议你从你筛选的项目开始你的比赛:

(t)<-[upvote:UPVOTED]-(:person)    
(t)<-[downvote:DOWNVOTED]-(:person)    
(t)<-[flag:FLAGGED]-(:person)    
即使如此,尽管你说的是:“找到一个主题,找出所有排列中有1个向上投票、无向下投票、无标志、1个向上投票、1个向下投票、无标志等的情况。”这意味着你要一次统计一个:

MATCH (t:topic)
WHERE ID(t)=4
OPTIONAL MATCH (t)<-[r:UPVOTED]-(:person)    
WITH t, COUNT(r) AS upvotes

OPTIONAL MATCH (t)<-[r:DOWNVOTED]-(:person)    
WITH t, upvotes, COUNT(r) AS downvotes

OPTIONAL MATCH (t)<-[r:FLAGGED]-(:person)    
RETURN upvotes, downvotes, COUNT(r) AS flags
匹配(t:主题)
其中ID(t)=4

可选匹配(t)检查此查询,我认为它将帮助您

MATCH(p:person)-[a:UPVOTED]->(t:topic),
(p) -[b:被否决]->(t),[p]-[c:被标记]->(t)
其中ID(t)=4

返回计数(a)作为a_计数,计数(b)作为b_计数,计数(c)作为c_计数;
一个更好的解决方案是使用
大小
,这将大大提高查询的性能:

MATCH (t:Topic)
WHERE id(t) = 4
RETURN size((t)<-[:DOWNVOTED]-(:Person)) as downvoted,
       size((t)<-[:UPVOTED]-(:Person)) as upvoted,
       size((t)<-[:FLAGGED]-(:Person)) as flagged
匹配(t:主题)
其中id(t)=4

返回大小((t)您当前的
匹配
要求相同的
人员
节点
(由
p
标识)与
t
具有所有3种类型的关系。这是因为标识符绑定到特定节点(或关系,或值),并且(除非被
WITH
子句隐藏,而您的查询中没有该子句)将在整个查询中引用相同的节点(或关系或值)

根据您的预期结果,我假设您只是试图计算任何
t
之间这三种类型的关系的数量。如果是这样,这是一种有效的方法:

MATCH (t:topic)
WHERE ID(t) = 4
MATCH (:person)-[r:UPVOTED|DOWNVOTED|FLAGGED]->(t)
RETURN REDUCE(s=[0,0,0], x IN COLLECT(r) |
  CASE TYPE(x)
    WHEN 'UPVOTED' THEN [s[0]+1, s[1], s[2]]
    WHEN 'DOWNVOTED' THEN [s[0], s[1]+1, s[2]]
    ELSE [s[0], s[1], s[2]+1]
  END
) As res;
res
是一个数组,其编号分别为
向上投票
向下投票
、和
标记的
关系,在任何
人员
t
之间


另一种方法是对每种关系类型使用单独的
可选MATCH
语句,返回三个
计数(不同的x)
值。但是上面的查询使用了一个
匹配
语句,大大减少了数据库命中次数,这通常是昂贵的。

不太清楚为什么会被否决……有人不喜欢我或neo4j?
MATCH (t:Topic)
WHERE id(t) = 4
RETURN size((t)<-[:DOWNVOTED]-(:Person)) as downvoted,
       size((t)<-[:UPVOTED]-(:Person)) as upvoted,
       size((t)<-[:FLAGGED]-(:Person)) as flagged
MATCH (t:topic)
WHERE ID(t) = 4
MATCH (:person)-[r:UPVOTED|DOWNVOTED|FLAGGED]->(t)
RETURN REDUCE(s=[0,0,0], x IN COLLECT(r) |
  CASE TYPE(x)
    WHEN 'UPVOTED' THEN [s[0]+1, s[1], s[2]]
    WHEN 'DOWNVOTED' THEN [s[0], s[1]+1, s[2]]
    ELSE [s[0], s[1], s[2]+1]
  END
) As res;