获得与节点和关系方向的间接关系

时间:2016-12-12 03:04:37

标签: neo4j cypher

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

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

gawk -v RS='\r\n' '{print $2}'

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

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

2 个答案:

答案 0 :(得分: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)

enter image description here

使用此查询:

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。关系是传出的(isOut),如果它从之前的( i-1。)关系的任何节点开始。
  4. 0.关系没有先前的关系,因此我们将其单独处理(isOutFirst)。
  5. 我们会将isOut值收集到isOuts列表。
  6. 我们将isOutFirst变量和isOuts列表合并到一个列表中。
  7. 您可以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)<-[r1]-(b)<-[r2]-(a),他们错误地将(b)<-[r2]-(a)标记为其中一条路径的传出。

答案 1 :(得分:0)

似乎我的问题不明确。请继续。根据之前的回答,我能够获得与节点的关系,如下所示。在这里,我不需要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])