Aaron
Aaron

Reputation: 686

gremlin query to n hops and traversal of all sub edges and nodes

I am trying to create a graph where i can find all relationships with given person and list of their friends.
the problem statement my graph looks like this

 bob ->friends -> jay
jay -> friends -> mack 

jay -> friends - > john 
mack -> friends -> trevor

given query where my original vertex is bob how can i show relation of

bob->jay->mack
bob->jay->john

if i do 3 hops it shold include relationship with mack-> trevor in result set

this is what i have this is the query i have thus far but it only produces resutls that are directly connected to bob and does not go out on otherV() as base selector and run 2 hops from connectedNode

results = g.V().has('person', 'bob').as('node').
union(
    bothE().hasLabel('friend').as('edge').otherV().has('person').as('connectedNode'),
    both().hasLabel('friend').dedup().as('connectedNode')
).
project('node', 'edge', 'connectedNode').
   by(select('node').valueMap().unfold().dedup().fold()).
   by(select('edge').valueMap().unfold().dedup().fold()).
   by(select('connectedNode').valueMap().unfold().dedup().fold()).
toList()

what should be the correct way to get the results?

Upvotes: 2

Views: 184

Answers (1)

stephen mallette
stephen mallette

Reputation: 46226

When asking questions about Gremlin it is best to include some sample data as a Gremlin script:

g.addV().property('person','bob').as('bob').
  addV().property('person','jay').as('jay').
  addV().property('person','mack').as('mack').
  addV().property('person','john').as('john').
  addV().property('person','trevor').as('trevor').
  addE('friends').from('bob').to('jay').
  addE('friends').from('jay').to('mack').
  addE('friends').from('jay').to('john').
  addE('friends').from('mack').to('trevor').iterate()

I think that the basics of this query are best accomplished with path():

gremlin> g.V().has('person','bob').out('friends').out('friends').path().by('person')
==>[bob,jay,mack]
==>[bob,jay,john]

I suppose that you have a situation where you might traverse in either direction on the "friends" edge, in which case you would probably want to use simplePath() to filter out cycles:

gremlin> g.V().has('person','bob').both('friends').both('friends').simplePath().path().by('person')  
==>[bob,jay,mack]
==>[bob,jay,john]

Perhaps an interesting case to consider is if you traverse from "jay":

gremlin> g.V().has('person','jay').both('friends').both('friends').simplePath().path().by('person') 
==>[jay,mack,trevor]

In this case we can see that we don't get the "[jay,john]" path because traversing from "john" has no edges that have not already been traversed so that path is filtered. We can work around that issue with repeat():

gremlin> g.V().has('person','jay').repeat(both('friends').simplePath()).emit(__.not(outE())).path().by('person')
==>[jay,john]
==>[jay,mack,trevor]

The key is the emit(__.not(outE())) where the repeat() will only produce vertices that have no further edges to traverse.

Upvotes: 1

Related Questions