Sunday, 17 May 2026

Finding Reachable Destinations with One Intermediate Step Using Gremlin Traversals

  

One of the strengths of Gremlin is how naturally it expresses multi-hop navigation in a graph. Instead of writing complex joins, you simply describe how you want to move from one vertex to another.

 

In this post, we’ll see how to answer a common graph question "Which services are called by Order Service through exactly one intermediate service?"

 

In this post, we’ll explore how out().out() works using a microservices dependency graph.

 

Domain: Microservices Dependencies

We’ll model:

·      Service vertices

·      CALLS edges from one service to another

 

This lets us ask "Which services are indirectly called by a given service (two hops away)?"

 

Sample Graph Setup (TinkerGraph)

graph = TinkerGraph.open()
g = graph.traversal()

// Services
serviceA = graph.addVertex(label, 'service', 'name', 'Order Service')
serviceB = graph.addVertex(label, 'service', 'name', 'Payment Service')
serviceC = graph.addVertex(label, 'service', 'name', 'Inventory Service')
serviceD = graph.addVertex(label, 'service', 'name', 'Notification Service')

// Dependencies
serviceA.addEdge('calls', serviceB)
serviceB.addEdge('calls', serviceC)
serviceC.addEdge('calls', serviceD)

 

gremlin> g.V().valueMap(true)
==>[id:0,label:service,name:[Order Service]]
==>[id:2,label:service,name:[Payment Service]]
==>[id:4,label:service,name:[Inventory Service]]
==>[id:6,label:service,name:[Notification Service]]
gremlin> 
gremlin> g.E().valueMap(true)
==>[id:8,label:calls]
==>[id:9,label:calls]
==>[id:10,label:calls]

   

Which services are called by Order Service through exactly one intermediate service?

 

g.V().
  has('service', 'name', 'Order Service').
  out('calls').
  out('calls').
  valueMap(true)

gremlin> g.V().
......1>   has('service', 'name', 'Order Service').
......2>   out('calls').
......3>   out('calls').
......4>   valueMap(true)
==>[id:4,label:service,name:[Inventory Service]]

How this traversal works?

·      has('service','name','Order Service'): Start from Order Service

·      out('calls'): Move to directly called services

·      out('calls'): Move one level deeper

·      values('name'): Return service names

 

Why out().out() Is Useful?

This traversal pattern is common in:

 

Domain

Example Question

Microservices

Indirect dependencies

Org charts   

Manager’s manager    

Supply chains

Tier-2 suppliers     

Data lineage 

Downstream consumers 

 

Each out() represents one hop in the graph. Chaining out() steps allows Gremlin to naturally express multi-level relationships without joins or recursion.

 

Instead of repeating out() twice, we can use 'repeat().times(2)'

g.V().
  has('service', 'name', 'Order Service').
  repeat(out('calls')).
  times(2).
  valueMap(true)

This traversal performs two consecutive out('calls') hops, just like out().out().

gremlin> g.V().
......1>   has('service', 'name', 'Order Service').
......2>   repeat(out('calls')).
......3>   times(2).
......4>   valueMap(true)
==>[id:4,label:service,name:[Inventory Service]]

   

Previous                                                    Next                                                    Home

No comments:

Post a Comment