Using your datamodel consisting of (:Person)-[:HAS_CHILD]->(:Person)
these queries should return the data you are looking for (let's also assume you have a unique name
property on each Person
node to facilitate a lookup by name, but you could also use any unique id/property):
A person and all his children
We can use a variable length path pattern here to match on patterns containing multiple HAS_CHILD
relationships.
MATCH (p:Person)-[:HAS_CHILD*]->(child:Person)
WHERE p.name = "Bob Loblaw"
RETURN child;
A person and his parent hierarchy
Very similar to the above query, but we just reverse the relationship direction.
MATCH (p:Person)<-[:HAS_CHILD*]-(ancestor:Person)
WHERE p.name = "Bob Loblaw"
RETURN ancestor;
Relationship between two person - if any
We can use the shortestPath
function to find the shortest path between two nodes in the graph. This query will return no rows if no path is found.
MATCH path=shortestPath((p:Person {name: "Bob Loblaw"})-[*]-(o:Person {name: "Louise Bluth"}))
RETURN path
A person and their child hierarchy - up to a specific depth
This query is very similar to the previous "person and all his children query" however we can specify bounds on the variable length path. Note: an upper bound should always be specified with variable length paths to avoid very long running queries.
MATCH (p:Person)-[:HAS_CHILD*1..5]->(child:Person)
WHERE p.name = "Bob Loblaw"
RETURN child;