我有像这样设置的数据
(Employee)-[:MANAGES]->(Employee)
它是严格等级的,即每个员工只有一个经理,顶部有一个老板。
当我这样做时
MATCH (e:Employee) RETURN count(e)
我得到 4197 。然后,当我做
MATCH
p=(e:Employee)<-[m:MANAGES*]-(:Employee {id: 'x'})
WITH
count(e) as people,
length(p) as distance
RETURN people, distance
ORDER BY distance DESC
x 是最高老板,我得到一个如下所示的列表:
╔═══════════╦═════════╗
║ DISTANCE ║ PEOPLE ║
╠═══════════╬═════════╣
║ 1 ║ 24 ║
║ 2 ║ 152 ║
║ 3 ║ 698 ║
║ 4 ║ 2019 ║
║ 5 ║ 3275 ║
║ 6 ║ 1942 ║
║ 7 ║ 117 ║
╚═══════════╩═════════╝
(顺便说一下,当我将星号为MANAGES改为 * 5 时,距离5的结果相同)
总和显然超过了总数,因此不知何故的东西被计算为双倍 - 这就是问题所在。我显然正在遭遇关于正在发生的事情的误解
答案 0 :(得分:2)
[为清晰起见而编辑。 - ed。]您需要将DISTINCT
关键字添加到COUNT
聚合语句中。
MATCH p = (e:Employee)<-[:MANAGES*]-(:Employee {id: 'x'})
WITH LENGTH(p) as distance, COUNT(DISTINCT e) as people,
RETURN people, distance
ORDER BY distance DESC
由于您选择的端点(员工)有多条路径,因此您在自动重复数据删除过程中会遇到一些深层次的伏都教。匹配路径模式将找到员工的路径,然后分配节点&amp;基于该路径的关系别名。除了匹配财产或在您的架构中确保您没有替代路线,或(更好)之外,无法找到一组单个节点(员工)使用路径查找和DISTINCT
的组合。下面的这个例子使它更清晰一点,虽然它更慢并且可能破坏信息:
MATCH (boss:Employee {id:'x'})
WITH boss
MATCH (e:Employee)<-[:MANAGES*]-(boss)
WITH DISTINCT e, boss
MATCH path = shortestPath( (e) <- [:MANAGES*] - (boss) )
RETURN length(path) AS distance, COUNT(e)
所以这只是找到所有落在老板下面的员工,确保(DISTINCT
)每个员工只能在一行中继续(没有重复),然后为每个员工找到< em>只是到老板的最短路径。现在,每个员工都有一个保证的单一路径,因此当您汇总和计算时,每人只能获得1个计数。
现在,如果你有&#34;横向&#34;之前的层次关系(员工有多条不同长度的 导致它们),此方法和上述方法将产生不同的数字。第一个示例中的DISTINCT
确保仅计算与老板特定距离的不同员工,因此同一员工可能出现在多行中。第二个例子虽然速度较慢,但首先将DISTINCT
应用于整个潜在员工组,然后仅将其计入管理的最短路径,这确实会丢失一些数据,但会确保总数一致。您可以考虑哪一个适合您的使用。
答案 1 :(得分:0)
令人费解。我猜测可能存在您不知道的数据问题。我假设id是唯一受约束的,因此作为完整性检查,请尝试此查询以查看是否有人被计算两次:
MATCH
(e:Employee)<-[m:MANAGES*]-(:Employee {id: 'x'})
WITH e, count(e) as occurrences
RETURN e, occurrences
WHERE occurrences > 1
ORDER BY occurrences DESC
如果有一些被计算两次,您可能需要检查由多个人管理的员工,这会导致他们在您的查询中被多次计算:
MATCH (e:Employee)
WITH e, SIZE( (e)<-[:MANAGES]-(:Employee) ) as managers
RETURN e, managers
WHERE managers > 1
ORDER BY managers DESC