2016-12-01 99 views
2

让我们考虑一个简单的例子,有两种类型的节点:公司和工人。对于任何一对公司c1和c2(我尊重一些我将忽略的条件),我需要知道:1.他们有多少共同工人,有多少工人有c1,有多少工人有c2。Neo4j Cypher路径使用几次相同的边

我的第一个猜测是:

MATCH (w_c1:Worker)--(c1:Company)--(w_common)--(c2:Company)--(w_c2:Worker) 
WHERE <something> 
RETURN c1, c2, COUNT(DISTINCT w_common), COUNT(DISTINCT w_c1), COUNT(DISTINCT w_c1) 

这一要求的问题是,如果我有任何对连接的节点,COUNT(DISTINCT w_c1)(ID为w_c2)之间只有一个链接就只算c1中不属于c2的工作人员。但是如果我在一些节点之间有几个关系,结果有时候是“正确的”。这听起来像比赛中的路径不会“回来”:(w_common) - (c2:公司) - (w_c2:工人)将不匹配(“worker1”) - (“company2”) - ( “worker1”)(这可能有助于避免无限循环)。

我的第二个猜测是两个部分分割的要求: 我的第一个猜测是:

MATCH (c1:Company)--(w_common)--(c2:Company) 
MATCH (c1)--(w_c1:Worker), (c2)--(w_c2:Worker) 
WHERE <something> 
RETURN c1, c2, COUNT(DISTINCT w_common), COUNT(DISTINCT w_c1), COUNT(DISTINCT w_c1) 

不过,结果是正确的,但我有一个关于笛卡尔积的警告,而事实上,在大数据集,我的请求不会在数小时后完成。我在两场比赛之间尝试了“WITH c1,w_common,c2”,但我仍然有警告

我该如何继续?

回答

1

有一件事会帮助你的是SIZE()函数,它可以告诉你一个模式的出现次数,例如:Worker per:Company。

这种查询可以为你工作,假设一个工人对公司的工作只有一个关系到公司:

MATCH (c1:Company)--(w_common:Worker)--(c2:Company) 
WHERE <your criteria for matching on a specific c1 and c2> 
RETURN COUNT(w_common) as inCommonCount, SIZE((c1)--(:Worker)) as c1Count, SIZE((c2)--(:Worker)) as c2Count 
+0

谢谢,我确实尝试了SIZE函数,但是我可能在给定的公司和工人之间有几个关系(例如对应于几个工作阶段)。 – Vandy

+1

您是否有特定的“:HIRED”,每个工人只能出现一次?然后你可以做一些像'size((c1) - [:HIRED] - >())'。 –

1

您可以使用小计:

OPTIONAL MATCH (C1:Company {name: 'c1'}) 
OPTIONAL MATCH (C2:Company {name: 'c2'}) 
WITH C1, C2 
MATCH (C:Company)<-[:workto]-(W:Worker) WHERE C = C1 OR C = C2 
WITH C1, C2, W, 
    sum(CASE WHEN C = C1 THEN 1 ELSE 0 END) as tmp1, 
    sum(CASE WHEN C = C2 THEN 1 ELSE 0 END) as tmp2 
RETURN C1, C2, 
     sum(tmp1) as cc1, sum(tmp2) as cc2, 
     sum(tmp1 * tmp2) as common