使用开始/结束日期过滤Neo4j中的关系

时间:2018-10-05 11:43:45

标签: neo4j cypher

我有一个图形模型-

(p:Person)-[r:LINK {startDate: timestamp, endDate: timestamp}]->(c:Company)

一个人可以同时链接到多个公司,并且一个公司可以同时有多个人链接到它(即,公司与人之间存在多对多关系)。

endDate属性是可选的,并且仅在某人离开公司后才会显示。

我正在尝试显示一个连接网络,并且可以使用以下密码查询成功地返回一个人的所有相关节点(这将显示2级的人际连接)-

MATCH (p:Person {id:<id>})-[r:LINK*0..4]-(l) RETURN *

我现在需要做的是过滤关系,使其在时间范围内匹配,例如第1个人在2000年1月1日至2002年12月31日在公司A工作。第二个人在2001年1月1日至2001年6月31日期间在公司A工作。第3个人在2005年1月1日之前在A公司工作,但仍在A公司。第1个人的结果应包括第2个人,但不包括第3个人。

此逻辑需要应用于图表的所有级别(我们允许用户显示3个级别的连接),并与每个级别中的父节点相关,即,在显示级别2时,人员2和日期的日期应该使用Person 3来过滤他们各自的关系。

从本质上讲,我们正在尝试执行与LinkedIn链接类似的操作,但要基于同时在公司工作的人员进行过滤。

我已经尝试过使用REDUCE函数,但是无法使逻辑适用于可选的结束日期-有人可以建议如何根据开始日期和结束日期过滤关系吗?

2 个答案:

答案 0 :(得分:1)

事实证明,日期范围可以有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 Procedures中的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。 >

获取配对后,我们需要确保在建议路径中所有有趣的关系对都符合您的条件并且重叠(或不重叠)。

答案 1 :(得分:0)

类似的事情应该起作用:

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提供。
  • 您希望variable-length relationship模式的下限为1(默认值)。如果您将0用作下界,那么您还将获得感兴趣的主要人物-这可能不是您想要的。
  • startDateendDate的值适合使用comparison operators进行比较