recursionneo4jcypher

Cypher Query to get a nested array of nodes at each level of a tree of nodes


I have a series of comments and replies, each comment can have multiple replies and each reply can in turn have any number of nested or immediate replies.

Here is some sample data graphed:

Here I have one post with 4 comments, each replied to the previous comment I would like to write a query so I can get them returned as nested lists like so

Post = {
   ...
   comments: [
      comment: {
          ...
          replies: [
              comment: {
                  ...
                  replies: [
                      comment : {
                         etc
                  ]
              }
          ]
      }
   ]
}

Where each comment has a list of replies and each of those replies has replies you get the point

I'm very new to using cypher I'm more familiar with mongoDB so this is the query I have so far

MATCH tree1 = (post:POST)<-[:COMMENTED_ON]-(comment:COMMENT)
OPTIONAL MATCH tree2 = (comment)<-[replied_to:REPLIED_TO *]-(reply:COMMENT)
WHERE ID(post) = 5
RETURN nodes(tree1), nodes(tree2)

Which gets all the nodes, but it's just the list of nodes, with a lot of repeats I've done a lot of googling, and I looked at the FOREACH functionality but I'm not sure how I would properly apply it here. I can almost definitely write a query that I can then use code to turn into the structure I need it to be in but it would be nice if I could write a query to do that for me or at least one that returns the nodes in a format where it's easier to do that


Solution

  • This query uses the APOC procedure apoc.convert.toTree to generate a tree:

    MATCH p = (post:POST)<-[:COMMENTED_ON]-(:COMMENT)-[:REPLIED_TO|COMMENTED_ON *0..]-(:COMMENT)
    WHERE ID(post) = 5
    WITH COLLECT(p) AS paths
    CALL apoc.convert.toTree(paths) YIELD value
    RETURN value
    

    Read the docs to see how to configure the properties that are included or excluded from the generated tree.