Usecase: Given a person (with a known id), find that person's all ancestors and all descendants.
Example:
Vertex:
Person1 (id=11) -> Person2 (id=22) -> Person3 (id=33) -> Person4 (id=44) -> Person5 (id=55)
Edge:
Every vertex can have almost two edges denoting the relationship:
Person1 (isParentOf) -> Person2 (isParentOf) -> Person3 (isParentOf) -> Person4 (isParentOf) -> Person5
Person1 <- (isChildOf) Person2 <- (isChildOf) Person3 <- (isChildOf) Person4 <- (isChildOf) Person5
E.g. Query 1:
Given Person1 (id=11), find Person1's all ancestors and all descendants.
Expected response: [isParentOf: 22 (Person2), 33 (Person3), 44 (Person4), 55 (Person(5)]
E.g. Query 2:
Given Person3 (id=33), find Person3's all ancestors and all descendants.
Expected response: [isChildOf: 22 (Person2), 11 (Person1), isParentOf: 44 (Person4), 55 (Person5)]
E.g. Query 3:
Given Person5 (id=55), find Person5's all ancestors and all descendants.
Expected response: [isChildOf: 44 (Person4), 33 (Person3), 22 (Person2), 11 (Person1)]
The response should keep the order of the ancestors and all descendants to help with other follow-up queries. The response should also contain the name property of the persons.
Test data populated at https://gremlify.com/pk9z0s6gv4g/5
g.addV('PERSON').property(id, '11').
property('name', 'person1').as('p1').
addV('PERSON').property(id, '22').
property('name', 'person2').as('p2').
addV('PERSON').property(id, '33').
property('name', 'person3').as('p3').
addV('PERSON').property(id, '44').
property('name', 'person4').as('p4').
addV('PERSON').property(id, '55').
property('name', 'person5').as('p5').
addE('isChildOf').from('p2').to('p1').
addE('isParentOf').from('p1').to('p2').
addE('isChildOf').from('p3').to('p2').
addE('isParentOf').from('p2').to('p3').
addE('isChildOf').from('p4').to('p3').
addE('isParentOf').from('p3').to('p4').
addE('isChildOf').from('p5').to('p4').
addE('isParentOf').from('p4').to('p5')
I tried the following example query:
g.V('33').repeat(out('isParentOf')).times(2).path()
Response
path[v[33], v[44], v[55]
My query has the following issues:
With my limited understanding of GraphDB and all the examples I have seen, the query must contain a limiting id and/or source+destination nodes (vertex) to traverse. I have not seen an open-ended query that traverses from a source node to a leaf node and vice-versa.
Using the Gremlin Console, here is an example that uses a union
step to search for both children and parents. I am a little curious why you modeled these both as outgoing relationships. If you modeled one as incoming and the other as outgoing, you could just have isParentOf
edges, and depending on the direction you travel (in or out), you could infer if someone is a child or a parent. Anyway, using the sample data:
gremlin> g.V('33').
......1> union(repeat(out('isChildOf')).until(__.not(out('isChildOf'))),
......2> repeat(out('isParentOf')).until(__.not(out('isParentOf')))).
......3> path().
......4> by('name')
==>[person3,person2,person1]
==>[person3,person4,person5]
Changing the query a bit, we can annotate the results to show the relationship type:
gremlin> g.V('33').
......1> union(project('child-of').by(repeat(out('isChildOf')).until(__.not(out('isChildOf'))).path().by('name')),
......2> project('parent-of').by(repeat(out('isParentOf')).until(__.not(out('isParentOf'))).path().by('name')))
==>[child-of:[person3,person2,person1]]
==>[parent-of:[person3,person4,person5]]
Pretty printed the query looks like this:
g.V('33').
union(
project('child-of').
by(
repeat(out('isChildOf')).until(__.not(out('isChildOf'))).
path().by('name')),
project('parent-of').
by(
repeat(out('isParentOf')).until(__.not(out('isParentOf'))).
path().by('name')))
Finally, if you do not want the starting person to appear in the results:
gremlin> g.V('33').
......1> union(
......2> project('child-of').
......3> by(
......4> repeat(out('isChildOf')).until(__.not(out('isChildOf'))).
......5> path().by('name').range(local,1,-1)),
......6> project('parent-of').
......7> by(
......8> repeat(out('isParentOf')).until(__.not(out('isParentOf'))).
......9> path().by('name').range(local,1,-1)))
==>[child-of:[person2,person1]]
==>[parent-of:[person4,person5]]