【问题标题】:Get indirect relationships with nodes and relationship direction获取与节点和关系方向的间接关系
【发布时间】:2016-12-12 03:04:37
【问题描述】:

我想以以下格式获取路径中的所有节点和关系:node1、node2、relationship-type、relationship-direction。

我尝试使用此查询获取路径。从这里我可以得到节点和关系。但无法得到关系的方向。

MATCH path = (e1:Entity)-[rel*1..4]-(e2:Entity)
WHERE e1._id = "222" AND  e2._id = "777"
RETURN path

我希望结果类似于返回直接关系的以下查询的输出。

MATCH (e1:Entity) WHERE e1._id = "222"
MATCH (e2:Entity) WHERE e2._id = "333"
MATCH (e1)-[rel]-(e2)
RETURN e1, e2, type(rel), (startNode(rel) = e1) as isOut

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    可以做到,但我找不到简单的解决方案。所以让我们来看看复杂的吧。

    首先,创建一个示例图:

    CREATE
      (a:Entity {name: 'a'}),
      (b:Entity {name: 'b'}),
      (c:Entity {name: 'c'}),
      (d:Entity {name: 'd'}),
      (e:Entity {name: 'e'}),
      (a)-[:REL {name: 'r1'}]->(b)
        <-[:REL {name: 'r2'}]-(c)
         -[:REL {name: 'r3'}]->(d)
         -[:REL {name: 'r4'}]->(e)
    

    使用这个查询:

    MATCH (e1 {name: 'a'})-[rels*1..4]-(e2 {name: 'e'})
    WITH e1, e2, rels,
      extract(rel IN rels | startNode(rel)) AS startNodes,
      extract(rel IN rels | endNode(rel)) AS endNodes,
      range(1, size(rels)-1) AS indexes
    WITH e1, e2, rels, startNodes, endNodes, indexes, startNodes[0] AS start
    UNWIND indexes AS i
    WITH e1, e2,
      e1 = start as isOutFirst, 
      (endNodes[i-1] = startNodes[i] OR
       startNodes[i-1] = startNodes[i]) AS isOut
    WITH e1, e2, isOutFirst, collect(isOut) AS isOuts
    RETURN e1, e2, [isOutFirst] + isOuts AS isOuts
    

    结果是:

    ╒═════════╤═════════╤═════════════════════════╕
    │e1       │e2       │isOuts                   │
    ╞═════════╪═════════╪═════════════════════════╡
    │{name: a}│{name: e}│[true, false, true, true]│
    └─────────┴─────────┴─────────────────────────┘
    

    主要思路如下:

    1. 我们使用extract 方法获取每个关系的开始和结束节点。
    2. 我们使用range 函数和UNWIND 生成索引列表并在列表上“迭代”。
    3. 如果 i. 关系从前一个 (i-1.) 关系的任何节点开始,则它是传出 (isOut) 关系。
    4. 0. 关系没有先前的关系,因此我们将其单独处理 (isOutFirst)。
    5. 我们将isOut 值收集到isOuts 列表中。
    6. 我们将isOutFirst 变量和isOuts 列表组合成一个列表。

    您可以UNWIND结果并添加对应的关系类型:

    MATCH (e1 {name: 'a'})-[rels*1..4]-(e2 {name: 'e'})
    WITH e1, e2, rels,
      extract(rel IN rels | startNode(rel)) AS startNodes,
      extract(rel IN rels | endNode(rel)) AS endNodes,
      range(1, size(rels)-1) AS indexes
    WITH e1, e2, rels, startNodes, endNodes, indexes, startNodes[0] AS start
    UNWIND indexes AS i
    WITH e1, e2, rels,
      e1 = start as isOutFirst, 
      (endNodes[i-1] = startNodes[i] OR
       startNodes[i-1] = startNodes[i]) AS isOut
    WITH e1, e2, rels, isOutFirst, collect(isOut) AS isOuts
    WITH e1, e2, rels, 
      [isOutFirst] + isOuts AS isOuts, 
      range(0, size(rels)-1) AS indexes2
    UNWIND indexes2 AS i
    RETURN e1, e2, type(rels[i]) AS relType, isOuts[i] AS isOut
    

    这会导致:

    ╒═════════╤═════════╤═══════╤═════╕
    │e1       │e2       │relType│isOut│
    ╞═════════╪═════════╪═══════╪═════╡
    │{name: a}│{name: e}│REL    │true │
    ├─────────┼─────────┼───────┼─────┤
    │{name: a}│{name: e}│REL    │false│
    ├─────────┼─────────┼───────┼─────┤
    │{name: a}│{name: e}│REL    │true │
    ├─────────┼─────────┼───────┼─────┤
    │{name: a}│{name: e}│REL    │true │
    └─────────┴─────────┴───────┴─────┘
    

    更新:您可以使用方向从路径中以正确的顺序提取节点:

    MATCH (e1 {name: 'a'})-[rels*1..4]-(e2 {name: 'e'})
    WITH e1, e2, rels,
      extract(rel IN rels | startNode(rel)) AS startNodes,
      extract(rel IN rels | endNode(rel)) AS endNodes,
      range(1, size(rels)-1) AS indexes
    WITH e1, e2, rels, startNodes, endNodes, indexes, startNodes[0] AS start
    UNWIND indexes AS i
    WITH e1, e2, rels,
      e1 = start as isOutFirst, 
      (endNodes[i-1] = startNodes[i] OR
       startNodes[i-1] = startNodes[i]) AS isOut
    WITH e1, e2, rels, isOutFirst, collect(isOut) AS isOuts
    WITH e1, e2, rels, 
      [isOutFirst] + isOuts AS isOuts, 
      range(0, size(rels)-1) AS indexes2
    UNWIND indexes2 AS i
    RETURN e1, e2, type(rels[i]) AS relType,
      CASE isOuts[i]
        WHEN true THEN startNode(rels[i])
        ELSE endNode(rels[i])
      END AS node1,
      CASE isOuts[i]
        WHEN true THEN endNode(rels[i])
        ELSE startNode(rels[i])
      END AS node2
    

    这会导致:

    ╒═════════╤═════════╤═══════╤═════════╤═════════╕
    │e1       │e2       │relType│node1    │node2    │
    ╞═════════╪═════════╪═══════╪═════════╪═════════╡
    │{name: a}│{name: e}│REL    │{name: a}│{name: b}│
    ├─────────┼─────────┼───────┼─────────┼─────────┤
    │{name: a}│{name: e}│REL    │{name: b}│{name: c}│
    ├─────────┼─────────┼───────┼─────────┼─────────┤
    │{name: a}│{name: e}│REL    │{name: c}│{name: d}│
    ├─────────┼─────────┼───────┼─────────┼─────────┤
    │{name: a}│{name: e}│REL    │{name: d}│{name: e}│
    └─────────┴─────────┴───────┴─────────┴─────────┘
    

    限制:如果图中有一个 2 长度的圆,上述解决方案可能不起作用,例如对于图形 (a)&lt;-[r1]-(b)&lt;-[r2]-(a),它们错误地将 (b)&lt;-[r2]-(a) 标记为其中一条路径的传出。

    【讨论】:

    • 感谢您的详细回答。似乎这在neo4j中非常复杂。除了将 e1 和 e2 作为起始节点和结束节点之外,我可以将它们作为相关关系的 from 和 to 节点吗?例如 a,b,REL,true b,c,REL,false c,d,REL,true d,e,REL,true
    • 当然 - 我用解决这个问题的方法扩展了答案。
    • @Prasad19sara 如果答案为您的问题提供了解决方案,请不要忘记将其标记为“已接受”。谢谢。
    【解决方案2】:

    似乎我的问题不清楚。抱歉。根据前面的答案,我能够为我的用例获得与节点的关系,如下所示。在这里我不需要 isOut 列,因为开始和结束节点都在那里。

    MATCH (e1 {_id: '222'})-[rels*1..4]-(e2 {_id: '777'}) WITH range(0, size(rels)-1) AS indexes,rels UNWIND indexes AS i RETURN startNode( rels[i]), type(rels[i]),endNode( rels[i])

    【讨论】:

    • 没问题,很高兴您为您的用例找到了一个简单的解决方案。但是请注意,在您的查询结果中,关系的开始和结束节点将分别为每个关系确定(而不是基于路径)。因此,对于路径 (a)-[:REL1]-&gt;(b)&lt;-[:REL2]-(c),您将获得以下行:a, REL1, bc, REL2, b,而不是 a, REL1, bb, REL2, c
    • 一个小提示:代码块使用 4 个空格的缩进而不是反引号。 (编辑器中有一个按钮可以执行此操作,或者只使用Ctrl + K。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-22
    • 1970-01-01
    • 1970-01-01
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多