Neo4j:计算属于两个不同连接类别的项目

时间:2018-06-06 09:59:03

标签: neo4j

我想计算并比较两个相关类别的项目数,但这些数字似乎不匹配。

假设我有一个图表,如:

CREATE (o1:Object {name:"CategoryA"})-[:CONNECTS_TO]->(o2:Object {name:"CategoryB"}),
       (i1:Instance {name:"Item1"})-[:IS_A]->(o1),
       (i2:Instance {name:"Item2"})-[:IS_A]->(o2),
       (i3:Instance {name:"Item3"})-[:IS_A]->(o2)

Object1连接到Object2,同时Object1与Item1关联,Object2与Item2和Item3关联。

然后我想计算每个对象的项目数:

MATCH (o1:Object)-[:CONNECTS_TO]->(o2:Object),
      (ix)-[:IS_A]->(o1), 
      (iy)-[:IS_A]->(o2) 
WITH o1, o2, COUNT(ix) AS o1_count, COUNT(iy) AS o2_count 
RETURN o1.name, o1_count, o2.name, o2_count

我原本期望的结果是:

"CategoryA" 1   "CategoryB" 2

但实际上我得到了:

"CategoryA" 2   "CategoryB" 2

有人能告诉我我做错了吗?

1 个答案:

答案 0 :(得分:1)

如果您只是返回匹配结果,您可以看到正在发生的事情:

MATCH (o1:Object)-[:CONNECTS_TO]->(o2:Object),
      (ix)-[:IS_A]->(o1), 
      (iy)-[:IS_A]->(o2)
RETURN o1, o2, ix, iy

你会得到这个回复:

╒════════════════════╤════════════════════╤════════════════╤════════════════╕
│"o1"                │"o2"                │"ix"            │"iy"            │
╞════════════════════╪════════════════════╪════════════════╪════════════════╡
│{"name":"CategoryA"}│{"name":"CategoryB"}│{"name":"Item1"}│{"name":"Item3"}│
├────────────────────┼────────────────────┼────────────────┼────────────────┤
│{"name":"CategoryA"}│{"name":"CategoryB"}│{"name":"Item1"}│{"name":"Item2"}│
└────────────────────┴────────────────────┴────────────────┴────────────────┘

恰好有两种模式适合您的匹配,这些模式的唯一区别是iy使用哪个节点。模式中的其余节点是相同的。

这里有完整的查询,因为o1o2有两种可能的模式(这些是非聚合变量),每个计数的计数为2(它只是其中一个ix,每次都是相同的节点。

您真正想要的是模式中不同节点的计数:

MATCH (o1:Object)-[:CONNECTS_TO]->(o2:Object),
      (ix)-[:IS_A]->(o1), 
      (iy)-[:IS_A]->(o2) 
WITH o1, o2, COUNT(distinct ix) AS o1_count, COUNT(distinct iy) AS o2_count 
RETURN o1.name, o1_count, o2.name, o2_count

这可以获得您想要的结果,因为在找到的路径中只有一个不同的ix节点,并且在找到的路径中有两个不同的iy节点。

更好的方法是甚至不使用计数聚合,而是从每个节点获得:IS_A关系的程度:

MATCH (o1:Object)-[:CONNECTS_TO]->(o2:Object)
WITH o1, o2, size(()-[:IS_A]->(o1)) AS o1_count, size(()-[:IS_A]->(o2)) AS o2_count 
RETURN o1.name, o1_count, o2.name, o2_count