# Family Tree Questions #748

Open
opened this issue Nov 17, 2019 · 6 comments
Open

# Family Tree Questions#748

opened this issue Nov 17, 2019 · 6 comments
Labels

### dandago commented Nov 17, 2019

 Hi, I've just gone through an exercise where I attempted to model a family tree using RedisGraph. I have just published this as my second RedisGraph article, Family Tree with RedisGraph. As a result of this exercise, I have a few questions on things that I wasn't sure how to do. First, is it possible to get a mixed tree (i.e. ancestors and descendants) in a single query as opposed to separate queries for ancestors and descendants? Secondly, given two people, is it possible to identify their relationship (e.g. sibling, cousin, uncle, parent, etc) based on the path between then, or would one need to run separate queries for each relationship type? Finally, what would be a good query to identify cousins? I'm not convinced with the one I'm using (below) as it should exclude the family where the person queried lies. ``````MATCH (x)-[:childOf*2]->(p)<-[:childOf*2]-(c) WHERE x.name = 'Donald' AND c.name <> 'Donald' RETURN c.name `````` I was thinking of a solution along the lines of having another `MATCH` clause to get the queried person's parents in order to exclude their children later in the `WHERE`, but there might be a more elegant way.

### swilly22 commented Nov 17, 2019

 Hi @dandago, Thank you for the tutorials! I must say I enjoy reading them. I hope you'll find my answers below useful Ancestors and descendants, `"MATCH (ancestor:Person)-[:childOf*1..]->(p:Person)-[:childOf*1..]->(descendant:Person) WHERE p.name = 'Donald' RETURN ancestor, descendant"` Using the `type` function on an edge will return the relationship type of that edge: `"MATCH ()-[e]->() RETURN type(e)"` Identify cousins: ``````MATCH (x)-[:childOf]-(parent:Person) WHERE x.name = 'Donald' WITH x as x, parent as parent MATCH (x)-[:childOf*2]->(grandParent:Person)<-[:childOf]-(uncle:Person)<-[:childOf]-(c:Person) WHERE uncle != parent RETURN c.name `````` RedisGraph will not avoid revisiting visited nodes.
added the label Nov 17, 2019

### dandago commented Nov 17, 2019

 Hi @swilly22, Thanks for your kind words and for your answers. Let's go through them: Ancestors and descendants: The query you provided gives pairs of ascendants and descendants. I'm sorry, I probably didn't explain myself clearly. I this case I'd like to get a single list consisting of both ancestors and descendants of the individual. Pretty much what I'm doing separately for ancestors and descendants, but I was hoping to do it in a single query. Now that I look at the docs again, it looks like I should be able to do this with a `UNION`. Relationships: the result of the query you provided gives: ``````1) 1) "type(e)" 2) 1) 1) "married" 2) 1) "childOf" 3) 1) "childOf" 4) 1) "married" 5) 1) "childOf" 6) 1) "childOf" 7) 1) "married" 8) 1) "married" 9) 1) "childOf" 10) 1) "childOf" 11) 1) "childOf" 12) 1) "childOf" 13) 1) "childOf" 14) 1) "childOf" 15) 1) "married" 16) 1) "childOf" 17) 1) "childOf" 18) 1) "childOf" 19) 1) "childOf" 3) 1) "Query internal execution time: 1.256898 milliseconds" `````` That's interesting, as I can see the relationship. However what I'd like is to be able to give it two individuals (e.g. Donald and Antoinette) and identify the family relationship (e.g. aunt). I'm not sure whether that's possible with a single query. Cousins: I've slightly modified your query as follows: ``````GRAPH.QUERY FamilyTree "MATCH (x)-[:childOf]->(parent:Person) WHERE x.name = 'Donald' WITH x as x, parent as parent MATCH (x)-[:childOf*2]->(grandParent:Person)<-[:childOf]-(uncle:Person)<-[:childOf]-(c:Person) WHERE uncle <> parent RETURN c.name" `````` I fixed an indirected relation in the first `MATCH`, changed `!=` to `<>`, and added a `DISTINCT`. I got this: ``````1) 1) "c.name" 2) 1) 1) "Donald" 2) 1) "Anthony" 3) 1) "George" 4) 1) "Bernard" 5) 1) "Fiona" `````` Unfortunately this isn't quite right because although it does return the cousins (Bernard and Fiona), it also returns Donald (the person whose cousins we want) and his children (Anthony and George). I'll see if I can play with this a little and get to a working solution. Thanks very much!

### DvirDukhan commented Nov 18, 2019

 hi @dandago Try to play with this query results `graph.query FamilyTree "match p=(:Person)-[:childOf*0..]->(:Person {name:'John'})-[:childOf*0..]->(:Person) return nodes(p)"`. This will return EVERY path from John's ancestors to his decedents. You will get partial paths that are part of longer paths that return in this query, but I believe that it is a start in the direction you want. Regarding your second question: In your graph Persons can have only `childOf` or`married` relationships with each other, and that's it. I think that given two people, you will have to work really hard and write a very complex query just to have the answer "aunt" or any answer Inferring their family hierarchy. More general approach for cousins: `graph.query FamilyTree "MATCH (c1:Person)-[:childOf]->(p1:Person)-[:childOf]->(:Person)<-[:childOf]-(p2:Person)<-[:childOf]-(c2:Person) WHERE p1 <> p2 return c1, c2"`
added the label Nov 18, 2019

### dandago commented Nov 18, 2019

 Hi @DvirDukhan, Thanks for your answers! The approach you took for No. 1 is interesting to say the least. I had no idea you could get paths like that. It's a shame that UNION is not supported, as it would have been a lot easier. For No. 2, is there a way to get the shortest path between the two given nodes? Because I could identify the type of family relationship by analysing the relationships in the path. Which I guess is pretty much what I'd do in an actual Cypher query, except that like this I can run a single query instead of one for each type of family relationship. For No. 3, that's pretty good! I modified it slightly to focus on a specific person, and it works perfectly: ``````graph.query FamilyTree "MATCH (c1:Person)-[:childOf]->(p1:Person)-[:childOf]->(:Person)<-[:childOf]-(p2:Person)<-[:childOf]-(c2:Person) WHERE p1 <> p2 AND c1.name = 'Donald' return c2.name" 1) 1) "c2.name" 2) 1) 1) "Bernard" 2) 1) "Fiona" 3) 1) "Query internal execution time: 1.903291 milliseconds" ``````

### swilly22 commented Nov 18, 2019

 @dandago UNION is supported.

### dandago commented Nov 18, 2019

 Yes, I just clarified that in #753. A working query for the ancestors & descendants is thus: ``````GRAPH.QUERY FamilyTree "MATCH (c)-[:childOf*1..]->(p) WHERE c.name = 'Donald' RETURN p.name AS name UNION MATCH (c)-[:childOf*1..]->(p) WHERE p.name = 'Donald' RETURN c.name AS name" 1) 1) "name" 2) 1) 1) "Christina" 2) 1) "Joseph" 3) 1) "Victoria" 4) 1) "John" 5) 1) "George" 6) 1) "Anthony" 3) 1) "Query internal execution time: 50.751127 milliseconds" ``````