LameCoder
LameCoder

Reputation: 1297

Neo4J Getting nodes from nodes in a path

This is sort of related to this question, but not quite the same: Performing a MATCH on all nodes on a path

Like in the previous question I have a similar setup:

(a)-->(b)-->(c)-->(d)
 ^     ^     ^     ^
 |r    |r    |r    |r
(aa)  (bb)  (cc)  (dd)

Example Create (See Console http://console.neo4j.org/r/vx99q):

CREATE 
    (a {name:'a'}),
    (b {name:'b'}),
    (c {name:'c'}),
    (d {name:'d'}),
    (aa {name:'aa'}),
    (bb {name:'bb'}),
    (cc {name:'cc'}),
    (dd {name:'dd'}),
    a-[:rel1]->b,
    b-[:rel1]->c,
    c-[:rel1]->d,
    a-[:r]->aa,
    b-[:r]->bb,
    c-[:r]->cc,
    d-[:r]->dd;

Let's say I have a as 7 and d as 4. I would get the path like this:

START a=node(7), d=node(4) 
MATCH path = a-[:rel1*]->d 
RETURN path

What I want is aa, bb, cc, and dd.

I'm stumped.

Upvotes: 0

Views: 336

Answers (1)

LameCoder
LameCoder

Reputation: 1297

Well it took a bit of wrapping my head around this, but I figured it out.

START n=node(*), a=node(1), z=node(4) 
MATCH path = a-[:rel1*]->z 
WITH n, path 
MATCH n-[:r]->o 
WHERE n IN path 
RETURN o

Though it does seem slow, I imagine that there is probably a better way to do it.

Output:

o
(5 {name:"aa"})
(6 {name:"bb"})
(7 {name:"cc"})
(8 {name:"dd"})

Edit: yhw42 mentioned that the query could run faster if modified like so:

START a=node(1), z=node(4) 
MATCH path = a-[:rel1*]->z 
WITH path 
MATCH n-[:r]->o 
WHERE n IN path 
RETURN o

In the sample, it did. My way was:

Query Results

+--------------------+
| o                  |
+--------------------+
| Node[5]{name:"aa"} |
| Node[6]{name:"bb"} |
| Node[7]{name:"cc"} |
| Node[8]{name:"dd"} |
+--------------------+
4 rows
344 ms

Execution Plan

ColumnFilter(symKeys=["n", "path", "o", "  UNNAMED88"], returnItemNames=["o"], _rows=4, _db_hits=0)
PatternMatch(g="(n)-['  UNNAMED88']-(o)", _rows=4, _db_hits=0)
  Filter(pred="any(-_-INNER-_- in path where n == -_-INNER-_-)", _rows=4, _db_hits=0)
    ColumnFilter(symKeys=["path", "n", "a", "  UNNAMED53", "z"], returnItemNames=["n", "path"], _rows=9, _db_hits=0)
      ExtractPath(name="path", patterns=["  UNNAMED53=a-[:rel1*]->z"], _rows=9, _db_hits=0)
        PatternMatch(g="(a)-['  UNNAMED53']-(z)", _rows=9, _db_hits=0)
          NodeById(name="Literal(List(4))", identifier="z", _rows=9, _db_hits=9)
            NodeById(name="Literal(List(1))", identifier="a", _rows=9, _db_hits=9)
              AllNodes(identifier="n", _rows=9, _db_hits=9)

His way was:

Query Results

+--------------------+
| o                  |
+--------------------+
| Node[5]{name:"aa"} |
| Node[6]{name:"bb"} |
| Node[7]{name:"cc"} |
| Node[8]{name:"dd"} |
+--------------------+
4 rows
174 ms

Execution Plan

ColumnFilter(symKeys=["path", "n", "o", "  UNNAMED74"], returnItemNames=["o"], _rows=4, _db_hits=0)
PatternMatch(g="(n)-['  UNNAMED74']-(o)", _rows=4, _db_hits=0)
  Filter(pred="any(-_-INNER-_- in path where n == -_-INNER-_-)", _rows=4, _db_hits=0)
    AllNodes(identifier="n", _rows=9, _db_hits=9)
      ColumnFilter(symKeys=["a", "z", "  UNNAMED42", "path"], returnItemNames=["path"], _rows=1, _db_hits=0)
        ExtractPath(name="path", patterns=["  UNNAMED42=a-[:rel1*]->z"], _rows=1, _db_hits=0)
          PatternMatch(g="(a)-['  UNNAMED42']-(z)", _rows=1, _db_hits=0)
            NodeById(name="Literal(List(4))", identifier="z", _rows=1, _db_hits=1)
              NodeById(name="Literal(List(1))", identifier="a", _rows=1, _db_hits=1)

Upvotes: 1

Related Questions