Skip to content

Backtrack Pattern

okram edited this page Feb 15, 2011 · 24 revisions

Many times its desirable to traverse a particular path and if some criteria is met along that path, then go back to the element from n-steps ago. Examples of such uses cases include:

  • “What is the age of my friends who have friends who are older than 30 years old?”
  • “What other products have my friends purchased who have also purchased a product of type X?”
g = TinkerGraphFactory.createTinkerGraph()

The query below says, in plain English: “What are the ages of the people that know people that are 30+ years old?” The call to back(3) refers to the elements 3 steps ago that have paths up to the back(3) step (i.e. back to the V step). In the example below, back(3) “wraps” outE('knows').inV{it.age > 30}.

gremlin> g.V.outE('knows').inV{it.age > 30}.back(3).age
==>29

A more complicated example is provided over the Grateful Dead graph diagrammed in Defining a More Complex Property Graph.

g = new TinkerGraph()
GraphMLReader.inputGraph(g, new FileInputStream('data/graph-example-2.xml'))

The example query below states the following:

  • get the song with id 89 (Dark Star).
  • get all the songs that follow Dark Star in concert.
  • get the singers of those songs.
  • filter to only those songs that are sung by Jerry Garcia.
  • go back 4 steps to yield those songs that follow Dark Star and are sung by Jerry Garcia.
  • get the names of those songs that follow Dark Star and are sung by Jerry Garcia.
gremlin> g.v(89).outE('followed_by').inV.outE('sung_by').inV[[name:'Garcia']].back(3).name
==>EYES OF THE WORLD
==>SING ME BACK HOME
==>MORNING DEW
==>HES GONE
==>CHINA DOLL
==>WHARF RAT
==>BROKEDOWN PALACE
==>TERRAPIN STATION
==>DEAL
==>ATTICS OF MY LIFE
==>COMES A TIME
==>STELLA BLUE
==>BERTHA

In order to determine how many steps to go back, the GremlinPipeline.toString() can be handy for displaying all the steps in an expression.

gremlin> println g.v(89).outE('followed_by').inV.outE('sung_by').inV[[name:'Garcia']]     
[VertexEdgeLabelFilterPipe<OUT_EDGES,followed_by>, EdgeVertexPipe<IN_VERTEX>, VertexEdgeLabelFilterPipe<OUT_EDGES,sung_by>, EdgeVertexPipe<IN_VERTEX>, PropertyFilterPipe<name,NOT_EQUAL,Garcia>]
==>null

Now, using the back step, notice how back(3) wraps 3 pipes prior to it. The name of the pipe in Pipes is FutureFilterPipe.

gremlin> println g.v(89).outE('followed_by').inV.outE('sung_by').inV[[name:'Garcia']].back(3).name
[VertexEdgeLabelFilterPipe<OUT_EDGES,followed_by>, EdgeVertexPipe<IN_VERTEX>, FutureFilterPipe<[VertexEdgeLabelFilterPipe<OUT_EDGES,sung_by>, EdgeVertexPipe<IN_VERTEX>, PropertyFilterPipe<name,NOT_EQUAL,Garcia>]>, PropertyPipe<name>]
==>null