在密码中,return 只有最近关系的节点

In cypher, return only the nodes with most recent relationship

其他问题相关,但从关系的另一端接近。

场景如下。我正在为一个生活或曾经生活在一个或多个不同地点的人建模。关系中包括他们搬进来的开始日期(从纪元开始以毫秒表示)。

    (:Person{name:'bill'}) -[:livesAt {since:1111000}]->(:Place{name:'apartmentA'})    
    (:Person{name:'bill'}) -[:livesAt {since:2222000}]->(:Place{name:'apartmentB'})
    (:Person{name:'john'}) -[:livesAt {since:3333000}]->(:Place{name:'apartmentA'})
    (:Person{name:'chris'}) -[:livesAt {since:1100000}]->(:Place{name:'apartmentC'})
    (:Person{name:'chris'}) -[:livesAt {since:1122000}]->(:Place{name:'apartmentA'})

我想编写一个查询,returns 仍然居住在给定位置的人员节点。如果 livesAt 关系具有来自那个人的所有关系中最大的“自”,他们仍然住在一个地方。

我正在尝试这样的事情:

MATCH (:Place {name: 'apartmentA'})<-[r]-(p:Person)
WITH max(r.since) as most_recent, p.name as pname
MATCH (t:Person {name:pname}) -[e]->(l:Place)
WITH t,l
ORDER BY e.since DESC
return t,l

如果我的查询适用于上面的示例,给定地点 'apartmentA' 我希望得到 john 和 chris。

要找到你想要的东西,你必须确保你过滤到那些与更大的人没有 :livesAt 关系的人,因为 属性(表明他们现在住在其他地方)到不同的地点。这很重要,因为他们有可能住在那个地方,搬到别处,然后又搬回去。

我们可以使用 Neo4j 中的存在子查询 4.x 来更好地控制描述我们不想存在的模式。

MATCH (loc:Place {name: 'apartmentA'})<-[r:livesAt]-(p:Person)
WITH loc, max(r.since) as most_recent, p
WHERE NOT EXISTS {
    MATCH (p) -[r:livesAt]->(other)
    WHERE r.since > most_recent AND other <> loc
}
RETURN p.name

您也可以考虑改造它,保持与他们当前住所的 :currentResidence 关系,并在他们搬家时更新(删除旧的,创建新的)。这是对您已有的 :livesAt 关系的补充(我假设您将这些关系用于其他查询)。这使您可以非常快速地根据当前居住地执行检查和匹配,而根本不需要进行任何额外的过滤。

编辑:

如果您不想使用存在子查询,我们可以改用模式的可选匹配,并且只过滤到另一个节点为空的结果,这意味着不存在这样的模式:

MATCH (loc:Place {name: 'apartmentA'})<-[r:livesAt]-(p:Person)
WITH loc, max(r.since) as most_recent, p
OPTIONAL MATCH (p) -[r:livesAt]->(other)
WHERE r.since > most_recent AND other <> loc
WITH p, other
WHERE other IS NULL
RETURN p.name