Reputation: 91
I am trying to find the hierarchy - both upward and downward for the following domain model. As being new to neo4j I am having some hurdle to get the right hierarchy with the cypher query.
Any assistance or sample would be a great help to me...
(:Person{id=1})-[HAS_CHILD]->(:Person{id=2})-[HAS_CHILD]->(:Person{id=3})-[HAS_CHILD]->(:Person{id=4})-[HAS_CHILD]->(:Person{id=5})
....like that to a very deep level & one person can have multiple children.
I am trying to build some query to find
A Person and all his children hierarchy
A person and his parent hierarchy
Relation ship between two person - if any
A Person and all his children hierarchy - up to a specific depth
Upvotes: 2
Views: 2435
Reputation: 67044
These should work.
The WHERE
clauses are for eliminating subpaths. The answer for #4 cannot use the same WHERE
clause, so the results will contain subpaths.
1.
MATCH p=(:Person{id:1})-[:HAS_CHILD*]->(c)
WHERE NOT (c)-[:HAS_CHILD]->()
RETURN NODES(p);
2.
MATCH p=(:Person { id:5 })<-[:HAS_CHILD*]-(ancestor)
WHERE NOT (ancestor)<-[:HAS_CHILD]-()
RETURN NODES(p);
3.
MATCH p=(p5:Person { id:5 })-[:HAS_CHILD*]-(p1:Person { id:1 })
RETURN NODES(p);
4. Using a depth up to 5:
MATCH p=(:Person{id:1})-[:HAS_CHILD*1..5]->(c)
RETURN NODES(p);
Upvotes: 4
Reputation: 8556
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;
Upvotes: 2