在密码中,只返回具有最近关系的节点



与另一个问题有关,但从关系的另一边接近。

下面是场景。我正在为一个生活或曾经生活在一个或多个不同地点的人建模。关系中包括他们移入的开始日期(自epoch以来以毫秒表示(。

(: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'})

我想写一个查询,返回仍然居住在给定位置的个人节点。他们仍然住在一个地方,如果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关系的人。这很重要,因为他们可能住在那个地方,搬到其他地方,后来又搬回来了。

我们可以使用Neo4j4.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关系的补充(我假设您将这些关系用于其他查询(。这让你可以非常快速地根据当前居住地进行检查和匹配,而无需进行任何额外的过滤。

编辑:

如果你不想使用存在子查询,我们可以使用模式的OPTIONAL MATCH,只过滤到其他节点为空的结果,这意味着不存在这样的模式:

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

最新更新