【问题标题】:Neo4j: Exclude certain nodes in variable path relationshipNeo4j:排除可变路径关系中的某些节点
【发布时间】:2021-08-17 14:37:00
【问题描述】:

我有一个图形数据库,由两种类型的节点(个人和企业)和一种关系类型(支付)组成。

一个人可以向另一个人或另一个企业付款。同样,企业可以向个人或企业付款。也就是说,这四种路径都是可能的

(person)-[:PAYS]->(person)
(person)-[:PAYS]->(business)
(business)-[:PAYS]->(person)
(business)-[:PAYS]->(business)

在检测可能存在洗钱的用例中,我想提取一个人的付款在到达另一个人之前经过几家企业的情况。也就是(为了方便省略关系):

(person)-(business)-(business)-(business)-(person)

因此,我的密码查询应如下所示:

(person)-[:PAYS*0..3]-(person)

但是,这也会返回以下关系,这不是我想要的:

(person)-(business)-(person)-(business)-(person)

如何从可变长度关系 [:PAYS*0..3] 中排除(人)?

我已经按照here 给出的解决方案进行了尝试:

MATCH path((person)-[:PAYS*0..3]-(person))
WHERE NONE(n IN nodes(path) WHERE n:person)
RETURN path

但是,此查询运行了很长时间,然后才给出零结果的输出(这是不正确的)。另一个明显的解决方案是更改我的关系以区分 [:PAYS_BUSINESS] 和 [:PAYS_PERSON],但我会在不更改我的图形模式的情况下找出解决方案是否可行。

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    原因

    MATCH path=((person)-[:PAYS*0..3]-(person))
    WHERE NONE(n IN nodes(path) WHERE n:person)
    RETURN path
    

    似乎没有任何结果是第一个和最后一个节点是人

    如果你想找到从 :person 到 :person 之间只有 :business 的路径,你可以这样做

    MATCH path=((p1:Person)-[:PAYS*1..3]-(p2:Person))
    WHERE ALL(n IN nodes(path)[1..-1] WHERE n:Business)
    RETURN path
    

    大家可能都想看看apoc.path.expandapoc.path.expandConfig 过程(https://neo4j.com/labs/apoc/4.1/overview/apoc.path/)。功能强大,但您引入了对 APOC 库的依赖。

    【讨论】:

      【解决方案2】:

      在我发布这个问题 5 分钟后,我想到并尝试了一个似乎可行的解决方案。不确定这是否违反规则,但这是解决我自己问题的一种可能方法(以防其他人面临同样的问题):

      MATCH x=(p1:person)-[:PAYS]-(b1:business)
      WITH *
      MATCH y=(b1:business)-[:PAYS*..3]-(b2:business)-[:PAYS]-(p2:person)
      RETURN x, y
      

      【讨论】:

        【解决方案3】:

        您可能想看看我是如何使用 X 链接继承来处理这个问题的。在该用例中,您可以聚合父母的性别(M 或 F),然后可以从聚合字符串中排除 MM,因为男人永远不会将 X 传递给他的儿子。

        http://stumpf.org/genealogy-blog/graph-databases-in-genealogy

        查询排除所有 MM 连接的字符串,而是接受除 MM 之外的任何内容:

        match p=(n:Person{RN:32})<-[:father|mother*..99]-(m) with m, reduce(status ='', q IN nodes(p)| status + q.sex) AS c, reduce(srt2 ='|', q IN nodes(p)| srt2 + q.RN + '|') AS PathOrder where c=replace(c,'MM','') return distinct m.fullname as Fullname
        

        在您的情况下,它是 P 和 B(个人或企业)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-06-14
          • 2022-11-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-05
          • 2023-03-19
          相关资源
          最近更新 更多