【问题标题】:Neo4j - Cypher return 1 to 1 relationshipsNeo4j - Cypher 返回 1 对 1 关系
【发布时间】:2013-11-09 11:12:22
【问题描述】:

使用 neo4j 1.9.2,我试图在我的图中找到与另一个节点具有一对一关系的所有节点。假设我的图表中有一些人,我想找到所有只有一个朋友(自 2013 年以来)的人,而这个朋友只有另一个人作为朋友,没有其他人。作为回报,我想拥有所有这些“孤立”的朋友。

我尝试了以下方法:

START n=node(*) MATCH n-[r:is_friend]-m-[s:is_friend]-n
WHERE r.since >= 2013 and s.since >= 2013
WITH n, m, count(r), count(s)
WHERE count(r) = 1 AND count(s) = 1
RETURN n, m

但是这个查询并没有做它应该做的事情——它只是什么也不返回。

注意:两个人之间只存在一种关系。所以一个朋友有一个传入的关系,另一个是一个传出的关系。另外,这两个人可能还有一些其他的关系,比如“works_in”左右,但我只想检查两个人之间是否存在 *is_friends* 类型的 1:1 关系。

编辑:如果使用 node(*) 作为起点,Stefan 的建议非常有效。但是,当尝试将此查询作为起点的一个特定节点(例如 start n=node(42))时,它不起作用。在这种情况下,解决方案会是什么样子?

更新:我仍然想知道这个场景的解决方案:如何检查给定的起始节点是否与特定关系类型的另一个节点具有一对一的关系。有什么想法吗?

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    了解MATCH 子句中的路径概念至关重要。路径是节点、关系、节点、关系……节点的交替集合。有一个约束条件是相同的关系永远不会在同一条路径中出现两次 - 否则会有无限循环的危险。

    也就是说,您需要确定您域中的 is_friend 是否被定向。如果它是定向的,您将区分 a 与 b 的朋友和 b 与 a 的朋友。从描述中我假设is_friend 是无向的,并且语句应该如下所示:

    START n=node(*) MATCH n-[r:is_friend]-()
    WHERE r.since >= 2013
    WITH n, count(r) as numberOfFriends
    WHERE numberOfFriends=1
    RETURN n
    

    你不必关心另一端,因为你做了node(*),它仍然被遍历。请注意,当您的图表增长时,node(*) 显然会变得更加昂贵。

    【讨论】:

    • 好的,你是对的,从 node(*) 开始时,你的建议工作正常。但是从单个起始节点开始时我将如何做到这一点?然后不检查该朋友只有一个朋友的约束。老实说,我实际上是从图表的一个子集开始。但是,对于这种情况,您的建议并没有返回整个图表中所有我孤立的朋友
    • 我的编辑呢?当从一个特定的起始节点开始时,我如何检查这个起始节点是否只有一个朋友,而这个朋友只有起始节点作为朋友,如果是这种情况,则返回两个节点。关于这种情况有什么建议吗?
    • 可以使用可选的matchMATCH n-[r?:is_friend]-(),注意r后面的问号
    • 对不起,但我看不出这有什么帮助。如下尝试不会检查起始节点的朋友是否只有起始节点作为朋友(并且没有其他其他朋友)。注意:我是从一个特定的起始节点开始,这里是节点 42。START n=node(42) MATCH n-[r?:is_friend]-() WHERE r.since >= 2013 WITH n, count(r) as numberOfFriends WHERE numberOfFriends=1 RETURN n
    • 这似乎真的可以解决问题!尽管我实际上打算从一个起始节点开始返回两个朋友(WITH n, m, collect(..))。但在这种情况下,我只是在第二个查询中重用结果。谢谢@jjaderberg!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 2015-10-07
    • 2020-11-12
    • 2017-07-08
    相关资源
    最近更新 更多