1
votes

I have a list of nodes stored as a chain in my neo4j graph database as given below:

root node1->neo4j->graph ->database.
root node2->neo4j->graph -> search.
root node3->neo4j->internals.

If I give a list of nodes(populated dynamically) as input , for e.g. “neo4j graph database”, I want to check for the given sequence of nodes and return the root folder.i.e.

neo4j graph database->root node1.

neo4j graph ->root node1, root node2.

neo4j ->root node1, root node2, root node3.


1

1 Answers

0
votes

First off, here is some data that looks like your sample. I made some assumptions that the data listed were all separate strands.

create (r1:Root {name: 'Root 1'})
create (n1:Node {name: 'Neo4j'})
create (n2:Node {name: 'Graph'})
create (n3:Node {name: 'Database'})
create r1-[:CONNECTED]->n1-[:CONNECTED]->n2-[:CONNECTED]->n3
create (r2:Root {name: 'Root 2'})
create (n4:Node {name: 'Neo4j'})
create (n5:Node {name: 'Graph'})
create (n6:Node {name: 'Search'})
create r2-[:CONNECTED]->n4-[:CONNECTED]->n5-[:CONNECTED]->n6
create (r3:Root {name: 'Root 3'})
create (n7:Node {name: 'Neo4j'})
create (n8:Node {name: 'Internals'})
create r3-[:CONNECTED]->n7-[:CONNECTED]->n8
return *

Now, here is a solution that works for ordered lists. The 0.. enables it to work with ordered lists with only one node.

// start with the ordered list of node names
with ['Neo4j', 'Graph', 'Database'] as ordered_list
// start by matching paths that begin with the first node
// in the ordered list and end with the last node
match p=((a:Node {name: ordered_list[0]})-[:CONNECTED*0..]-(b:Node {name: ordered_list[length(ordered_list)-1]}))
// collect these as the list of potential candidates
with collect(p) as candidates, ordered_list
// pass through the list and only keep the candidates that are 
// the same length as the ordered list
unwind candidates as candidate
with case when (length(nodes(candidate)) = length(ordered_list)) 
  then candidate
end as candidate, ordered_list
// recollect the filtered candidates
with collect(candidate) as candidates, ordered_list
// pass through the candidates now again and compare the names
// of the ordered list to the original ordered list
// only keep those that match as matched
unwind candidates as candidate
with case 
  when reduce(names = [], n in nodes(candidate) | names + n.name) = ordered_list 
  then candidate
end as matched
// with the matched nodes find the root node that is attached to
// first node in each matched path
match (r:Root)--(head:Node)
where id(head) = id(nodes(matched)[0])
// return the root and the matched path nodes
return r.name, nodes(matched)