cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Running new MATCH to all nodes in a PARENT/CHILD path and still return a path

I have a hierarchical parent/child structure that I wish to return as a tree. I can use apoc.convert.toTree to return the tree and that works great. Since my graph's parent/child structure is somewhat like a file folder structure, to simplify, I'll just use folders as an example. The following example returns a tree with the folders and sub-folders nested under one parent folder.

MATCH (parent:Folder)
WHERE id(parent) = {parentId}
OPTIONAL MATCH childPath= (child:Folder)-[:CHILD*]->(endFolder:Folder)
	WHERE (parent)-[:CHILD]->(child)
WITH childPath, endFolder
ORDER BY endFolder.name
WITH collect(childPath) as paths
CALL apoc.convert.toTree(paths) YIELD value
RETURN value

The part that is stumping me, is returning the 'creator' of each folder to return into the tree because each folder in the path has the relationship (:Folder)-[:CREATED_BY]->(:Person). Since the path could be unlimited length, I find all the sub folders with the [:CHILD*] relationship, which allows me to run a MATCH on the start and end of the path but this does not allow me to run a MATCH on ALL the nodes. Then I still need to turn the data back into a path to return the nested tree.

I feel like I want to collapse the Folder/Person relationship down to a virtual nodes, recreate the folder relationships as virtual relationships and then generate the hierarchical paths, but once I create a virtual node/relationships, it doesn't seem like I can do a MATCH off of it to generate a path. Is there a different approach that anyone else has taken to 'branch out' another relationship of my path?

1 REPLY 1

Hi morehtancarbon,

Welcome to the community!
I will try to answer your question. And I hope i understand your question.
First a cypher comment:
You are doing OPTIONAL MATCH childPath=(child...) you can remove the OPTIONAL part and use a 0 in your variable path query:
I should write it like this:

MATCH (parent:Folder)-[:CHILD]->(child:Folder)
WHERE id(parent) = {parentId}
WITH child
MATCH childPath=(child)-[:CHILD*0..]->(endFolder:Folder)
with childPath, endFolder order by endFolder.name
...

To solve the 'creator' structure i would add the CREATED_BY as a possible relationship type something like this:

MATCH (parent:Folder)-[:CHILD]->(child:Folder)
WHERE id(parent) = {parentId}
WITH child
MATCH childPath=(child)-[:CHILD:CREATED_BY*0..]->(endFolderOrPerson)
with childPath 
,      CASE WHEN endFolderOrPerson:Folder THEN endFolder.name ELSE '___' END as orderField order by orderField
with collect(childPath) as paths
CALL apoc.convert.toTree(paths) yield value
RETURN value

you will now have a "created_by" element in the returned map.

the simplest way is to add a createdBy property on the Folder Node....

Does this help?

Regards
Kees