1
votes

I'm modeling a set of nodes which has some hierarchical relationships (as a PARENT relationship) but additionally some non-hierarchical relationship.

Let's say it's a family tree with relationships to the birth country for each person, for simplicity

So each birth country is a node and each person is a node, and I might create the relationship in cypher as:

start parent=node(123), child=node(456)
create parent-[:PARENT]->child;

and

start person=node(123), country=node(789)
create person-[:BORN_IN]->country;

what I'd like to do is, for example, get a list of folks who don't have any ancestors from England, or folks who do have an ancestor from Japan, or the like. I feel like this should be a reasonable query, but I am new to cypher and haven't a clue how to construct it.

UPDATE ** After more extensive testing of cases, I've found that the query doesn't work exactly right in some. Given a child with one parent from England and a grandparent not from England, a query for children without any ancestors from England incorrectly returns the child with a parent from England. It looks like the way I've written the query, I get a return for the grandparent having a NULL relationship to england. My query is as follows:

START n=node(*), ancestor=node(123)
MATCH n-[r:PARENT*]->o-[b?:BORN_IN]->ancestor
WHERE b IS NULL 
RETURN DISTINCT n;

If all the person's ancestors were born in the country in question, it works fine.

1

1 Answers

4
votes

You can use a variable length relation to include all children/ancestors. I just picked the "folks who do have an ancestor from Japan":

START country=<lookup Japan>
match (child)-[:PARENT*0..5]->(parent)-[:BORN_IN]->(country)
return child

Note: have not tried it but logically this should do it. Also I picked a random depth of 5.

MATCH a-[:PARENT]->b-[:BORN_IN]->z 

as mentioned in your example should find all persons (a) who have a parent born in z

If you have a data set handy on console.neo4j.org maybe, could take a look at what's happening.