-
Notifications
You must be signed in to change notification settings - Fork 239
Backtrack Pattern
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.filter{it.age > 30}
.
gremlin> g.V.outE('knows').inV.filter{it.age > 30}.back(3).age
==>29
gremlin> g.V.as('x').outE('knows').inV.filter{it.age > 30}.back('x').age
==>29
A more complicated example is provided over the Grateful Dead graph diagrammed in Defining a More Complex Property Graph.
g = new TinkerGraph()
g.loadGraphML('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.has('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.has('name','Garcia')
[StartPipe, OutEdgesPipe(followed_by), InVertexPipe, OutEdgesPipe(sung_by), InVertexPipe, PropertyFilterPipe(name,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 BackFilterPipe
.
gremlin> println g.v(89).outE('followed_by').inV.outE('sung_by').inV.has('name','Garcia').back(3).name
[StartPipe, OutEdgesPipe(followed_by), InVertexPipe, BackFilterPipe([OutEdgesPipe(sung_by), InVertexPipe, PropertyFilterPipe(name,EQUAL,Garcia)]), PropertyPipe(name)]
==>null
Moreover, you can use as
to label a back point.
gremlin> println g.v(89).outE('followed_by').inV.as('x').outE('sung_by').inV.has('name','Garcia').back('x').name
[StartPipe, OutEdgesPipe(followed_by), AsPipe(x,InVertexPipe), BackFilterPipe([OutEdgesPipe(sung_by), InVertexPipe, PropertyFilterPipe(name,EQUAL,Garcia)]), PropertyPipe(name)]
==>null