eShark
eShark

Reputation: 91

Neo4j: hierarchy finding cypher query

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

  1. A Person and all his children hierarchy

  2. A person and his parent hierarchy

  3. Relation ship between two person - if any

  4. A Person and all his children hierarchy - up to a specific depth

Upvotes: 2

Views: 2435

Answers (2)

cybersam
cybersam

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

William Lyon
William Lyon

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

Related Questions