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
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);
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;
Related
My database stores family relationships.
What I am trying to do is to return the whole family tree of a person with a certain ID.
I have tried the following query:
MATCH (p:Person {id:'1887'})-[r*1..3]-(k:Person)
RETURN distinct(p), r, k
but I didn't get the result that I wanted.
To make it more clear, I would like to get all the relationships that a person with specified ID has, along with the relationships of all the other nodes that he is connected to.
To explain further, here is an example:
Boris is a parent of Mike and Anna. Apart of seeing Boris' relationship to them, I also want to see Mike and Anna's further relationships with their subgraphs.
I believe you should try returning the complete path, like this:
MATCH path = (p:Person {id:'1887'})-[r*1..3]-(k:Person)
RETURN path
This query will store each the path between a person with id = 1887 and another person with depth 1 to 3 and return it. Or if you are interested only in the nodes you can extract it with the nodes() function:
MATCH path = (p:Person {id:'1887'})-[r*1..3]-(k:Person)
RETURN nodes(path)
suppose I have a tree where certain nodes have a relationship of a give type, how would I return all nodes in the tree except for those with the given relationship and its descendants.
I've gotten half way there with something like this (the tree is built on has links):
match (root: {Name: 'Root'})-[:has*]->(n) where not (n)-[:Exemption]-() return n
but, of course, this excludes nodes that have a relationship of type Exemption but not its descendants, so the descendants show up as unconnected nodes
how do I structure the query?
This query should work:
MATCH p=({Name: 'Root'})-[:has*]->(n)
WHERE NONE(x IN NODES(p) WHERE (x)-[:Exemption]-())
RETURN n;
It filters out any :has relationship paths with a node that (also) has an :Exemption relationship.
I would probably split the path up into two parts:
MATCH p=(:Label {Name: 'Root'})-[:has*]->(n) WHERE NOT EXISTS ((n)-[:Exemption]->())
MATCH p2 = (n)-[:has*]->(m) WHERE NOT (m)-[:has]->()
RETURN p,p2;
after some experimentation, this worked:
match (root: {Name: 'Root'})-[:has*]->(n)
match (m)-[:has*]->(n)
where not (m)-[:Exemption]-()
return n
which essentially says: find a path, for any node on that path, traverse back up to make sure that none of the ancestors show an exception. so what I'm negating here is the subpath created with the second match
I have a simple graph with nodes labeled as Organization and two directed relationship types 'Control' and 'Influence'. My objective is -
Step-1
Given a node, find all nodes connected to it with 'Control' relationship (in any direction)
Step-2
For all nodes found by Step-1, find any outbound 'Influence' relationships (of any length) and include those nodes as well
What I have been able to come up thus far:
MATCH (x:Organization {ORGID: "5621"})-[:Control*1..]-(y) WITH y MATCH y-[:Influence*0..]-(z) RETURN y,z;
Questions
1) This query does not include the starting node, how can I get that in the result?
2) Ideally I'd like to get the relationships in the result also, it just returns the nodes
TIA
Here is one way to do what you want:
MATCH (x:Organization { ORGID: "5621" }), p1 = x-[:Influence*0..]->(z)
WHERE NOT z-[:Influence]->()
WITH x, COLLECT(p1) AS c1
OPTIONAL MATCH x-[:Control*]-(y), p2=y-[:Influence*0..]->(z)
WHERE NOT z-[:Influence]->()
RETURN c1 + COLLECT(p2) AS result;
The query returns a collection of matching Influence paths. The WHERE clauses are used to make sure that each path is as long as possible (to avoid a lot of duplicate subpaths from showing up in the results). Every path is a collection of node(s) separated by relationships, and can consist of just a node if the path has no relationships.
I am trying to follow a certain relationship type and return all the nodes and (other) relationships on that path but not to follow paths through nodes that are not part of the path.
Below is the live query that I have set up to demonstrate.
http://console.neo4j.org/?id=b6sxoh
In the example I do not want the relationship through B->E->C to be included in the results because there is no 'depends_on' relationship between them.
Below is one of my many attempts... (also in the console).
START me=node:node_auto_index(name='A')
MATCH p=me-[d:depends_on*]->others
WITH me,others
MATCH p=me-[r*]-others
RETURN DISTINCT relationships(p);
I would love some help please!
One way to do this is to iterate through each pair of nodes on the matched path for the pattern "p=me-[d:depends_on*]->others", and find any other relationships between them.
START me=node:node_auto_index(name='A')
MATCH me-[:depends_on*0..]->(previous)-[:depends_on]->last
With previous, last
Match previous-[r]-last
Where type(r) <> 'depends_on'
Return r
Since each matched path for the pattern "me-[d:depends_on*]->others" is augmented with a new relationship as the last relationship, to iterate through all the relationships on the matched path is to iterate through each last relationship on the matched paths. So for each matched path, we capture the start node and the end node of the last relationship as "previous" and "last" and then find the relationships "r" between them, filter "r" with the "Where" clause based on the type of the relationship r, return only those relationships r that are not of the type "depends_on".
I'm using a query similar to this one:
(n)-[*]->(m)
Any depth.
But I cannot filter the relation name in such a query like this:
(n)-[*:DOES]->(m)
Any depth.
I need to filter the relation name since there are different relations on the related path. If it helps, here is my graph:
CREATE (Computer { name:'Computer' }),(Programming { name:'Programming' }),(Java { name:'Java' }),(GUI { name:'GUI' }),(Button { name:'Button' }), Computer<-[:IS]-Programming, Programming<-[:IS]-Java, Java<-[:IS]-GUI, GUI<-[:IS]-Button, (Ekin { name:'Ekin' }), (Gunes { name:'Gunes' }), (Ilker {name:'Ilker'}), Ekin-[:DOES]->Programming, Ilker-[:DOES]->Java, Ilker-[:DOES]->Button, Gunes-[:DOES]->Java
I'd like to get the names (Ekin, Ilker and Gunes) which have "DOES" relationship connected to "Programming" with any depth.
Edit:
I'm able to get the values I want by merging two different queries' results (think 13 is the top node that I want to reach):
START n=node(13)
MATCH p-[:DOES]->()-[*]->(n)
RETURN DISTINCT p
START n=node(13)
MATCH p-[:DOES]->(n)
RETURN DISTINCT p
I want to do it in a single query.
Change the matching pattern to "p-[:DOES]->()-[*0..]->n",
Match p-[:DOES]->()-[*0..]->n
Return distinct p.name
The variable length relationship "[*]" means 1..*. You need 0..* length relationships on the path.
Just to update the answer with Neo4j 3.0.
MATCH p-[:DOES*0..]->(n)
RETURN DISTINCT(p.name)
It returns the same result as the accepted answer.