我有一个图模型 -
(p:Person)-[r:LINK {startDate: timestamp, endDate: timestamp}]->(c:Company)
一个人可以同时与多个公司联系,一个公司可以有多个人同时链接到它(即公司和人之间存在多对多的关系)。
endDate属性是可选的,只有在一个人离开公司时才会出现。
我正在尝试显示一个连接网络,并且可以使用以下密码查询成功返回一个人的所有相关节点(这将显示两级人员连接) -
MATCH (p:Person {id:<id>})-[r:LINK*0..4]-(l) RETURN *
我现在需要做的是过滤关系在时间范围内匹配的关系,例如: 1人于2000年1月1日至2002年12月31日期间在A公司工作。人员2于01/01/2001至31/06/2001期间在A公司工作。第3人于2005年1月1日在A公司工作,现仍在A公司。第1人的结果应包括第2人但不包括第3人。
这个相同的逻辑需要应用于图的所有级别(我们允许用户显示3个级别的连接)并且与每个级别中的父节点相关,即当显示级别2时,Person 2和Person 3的日期应该用于过滤各自的关系。
从本质上讲,我们尝试做类似LinkedIn连接的事情,但要根据同时在公司工作的人进行过滤。
我已经尝试过使用REDUCE函数,但无法使逻辑适用于可选的结束日期 - 有人可以建议如何根据开始和结束日期过滤关系吗?
事实证明,有4种方式可以使日期范围重叠,但只有2种方式可以重叠(人1在人2开始之前结束,或人2在人1开始之前结束),所以检查这两种方式都不容易存在这些无重叠条件。
在1级的情况下,这个查询应该做的伎俩:
MATCH (start:Person{id:1})-[r1:LINK]->(c)<-[r2:LINK]-(suggest)
WHERE NOT ((r1.endDate IS NOT NULL and r1.endDate < r2.startDate)
OR (r2.endDate IS NOT NULL and r2.endDate < r1.startDate))
RETURN suggest
棘手的部分是将其应用于多个级别。
虽然我们可以创建一个单独的Cypher查询来动态处理这种情况,但是关系的评估只会在扩展之后发生,而不是在发生期间,所以它可能不是最有效的:
MATCH path = (start:Person{id:1})-[:LINK*..6]-(suggest:Person)
WITH path, start, suggest, apoc.coll.pairsMin(relationships(path)) as pairs
WITH path, start, suggest, [index in range(0, size(pairs)-1) WHERE index % 2 = 0 | pairs[index]] as pairs
WHERE none(pair in pairs WHERE (pair[0].endDate IS NOT NULL AND pair[0].endDate < pair[1].startDate)
OR (pair[1].endDate IS NOT NULL AND pair[1].endDate < pair[0].startDate))
RETURN suggest
这里的一些亮点......
我们使用来自APOC程序的apoc.coll.pairsMin()
从每条路径中的关系集合中获取相邻关系对,但我们只对偶数条目(来自同一公司工作人员的两种关系)感兴趣,因为奇数对对应于来自同一个人到两个不同公司的关系。
所以如果我们在这个模式上执行:
MATCH path = (start:Person)-[r1:LINK]->(c1)<-[r2:LINK]-(person2)-[r3:LINK]->(c2)<-[r4:LINK]-(person3)
apoc.coll.pairsMin(relationships(path))
将返回[[r1, r2], [r2,r3], [r3,r4]]
,你可以看到我们需要考虑的关系是将2个人链接到公司的关系,因此对列表中的索引0和2。
在我们获得配对后,我们需要确保考虑建议的路径中的所有有趣关系对符合您的标准并重叠(或不重叠)。
这样的事情应该有效:
MATCH path=(p:Person {id: $id})-[r:LINK*..4]-(l)
WHERE ALL(x IN NODES(path)[1..] WHERE x.startDate <= p.endDate AND x.endDate >= p.startDate)
RETURN path;
假设:
id
值由$id
parameter提供。startDate
和endDate
的值适合使用comparison operators进行比较