Gremlin's Anatomy

Gremlin's Anatomy
Stephen Mallette
@spmallette
© 2018. All Rights Reserved.
© 2018. All Rights Reserved.
What is a graph?
© 2018. All Rights Reserved.
● A property graph is a collection of vertices and
edges
○ A vertex represents entities/domain objects
○ An edge represents a directional relationship between
two vertices
○ Vertices and edges have labels and properties
label: person
name: Stephen
label: company
name: DataStax
label: person
name: Paras
label: employs
since: 2015
label: employs
since: 2016
label: knows
© 2018. All Rights Reserved.
How does Apache
TinkerPop support
graph processing?
© 2018. All Rights Reserved.
© 2018. All Rights Reserved.
Gremlin's Anatomy refers to the
study of the Gremlin graph
traversal language at a level
beyond just reference to the set
of steps that define the language
itself.
© 2018. All Rights Reserved.
● Reasons to study Gremlin's Anatomy
○ Write better Gremlin
○ Improve ability to read more
complex Gremlin
○ Ask more concise questions if you
get stuck
○ Develop more robust and
expressive Domain Specific
Languages
© 2018. All Rights Reserved.
g.V()
GraphTraversalSource
● Spawns GraphTraversal
instances with start
steps
● Holds configurations that
Gremlin will use in the
traversal
© 2018. All Rights Reserved.
g.V().
has('movie', 'title',
'Young Guns').
outE().
groupCount()
GraphTraversal
● The steps that make up
the Gremlin language
● Each step returns a
GraphTraversal so that
steps can be chained
together
● The output of one step
becomes the input to the
next
© 2018. All Rights Reserved.
g.V().
has('movie', 'title',
'Young Guns').
outE().
groupCount().
by()
Step Modulators
● Step modulators look
back on the previous
step and modifies their
behavior
© 2018. All Rights Reserved.
g.V().
has('movie', 'title',
'Young Guns').
outE().
groupCount().
by(label())
Anonymous Traversal
● A traversal not bound to
a GraphTraversalSource
● Spawned from the
double underscore class
(e.g __.label())
● Usually exposed as
standalone functions for
better readability
© 2018. All Rights Reserved.
g.V().
has('movie', 'title',
within('Young Guns',
'Hot Shots!')).
outE().
groupCount().
by(label())
Expressions
● Typically refers to string
tokens, enums or
Predicate values (i.e.
anything that makes
Gremlin more readable)
● Be aware of naming
collisions with steps and
other expressions (e.g.
P.not() and not()
step).
© 2018. All Rights Reserved.
g.V().
has('movie', 'title',
within('Young Guns',
'Hot Shots!')).
outE().
groupCount().
by(label()).next()
Terminal Steps
● Steps that do not return a
traversal and instead
return the traversal result.
● Commonly used terminal
steps include hasNext(),
next(), iterate(), toList().
● If you don't have a terminal
step, you don't have a
result. You just have a
GraphTraversal.
© 2018. All Rights Reserved.
The Gremlin Debugging Cycle
presents methods and
techniques that provide insight
into Gremlin statements of any
complexity for purposes of
learning, debugging, and crafting
traversals.
© 2018. All Rights Reserved.
https://stackoverflow.com/a/47680050/1831717
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
label: rates
tag: ruby
value: 8
label: rates
tag: ruby
value: 9
© 2018. All Rights Reserved.
Sample Graph
name: alice name: bobby name: cindy
label: rates
tag: ruby
value: 7
name: david
label: rates
tag: ruby
value: 6
name: eliza
label: rates
tag: java
value: 10
© 2018. All Rights Reserved.
,,,/
(o o)
-----oOOo-(3)-oOOo-----
plugin activated: tinkerpop.server
plugin activated: tinkerpop.utilities
plugin activated: tinkerpop.tinkergraph
gremlin>
© 2018. All Rights Reserved.
gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> g = graph.traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV().property('name','alice').as('a').
......1> addV().property('name','bobby').as('b').
......2> addV().property('name','cindy').as('c').
......3> addV().property('name','david').as('d').
......4> addV().property('name','eliza').as('e').
......5> addE('rates').from('a').to('b').property('tag','ruby').property('value',9).
......6> addE('rates').from('b').to('c').property('tag','ruby').property('value',8).
......7> addE('rates').from('c').to('d').property('tag','ruby').property('value',7).
......8> addE('rates').from('d').to('e').property('tag','ruby').property('value',6).
......9> addE('rates').from('e').to('a').property('tag','java').property('value',10).
.....10> iterate()
gremlin> graph
==>tinkergraph[vertices:5 edges:5]
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold()).
.....15> unfold().
.....16> sack(assign).
.....17> by(constant(1d)).
.....18> sack(div).
.....19> by(union(constant(1d),
.....20> tail(local, 1)).sum()).
.....21> sack(mult).
.....22> by(limit(local, 1)).
.....23> sack().sum()).
.....24> cap('a')
==>[alice,[alice,bobby,cindy,david,eliza,alice],[9,8,7,6,10],18.833333333333332]
© 2018. All Rights Reserved.
Isolate for
Analysis
Clarify
Results
Validate
Assumptions
1
23
Gremlin Debugging Cycle
© 2018. All Rights Reserved.
Isolate a portion of the larger Gremlin statement
for analysis. The isolated portion should be only
as long as you are capable of following by just
reading the code.
Isolate for Analysis 1
© 2018. All Rights Reserved.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice'))
==>v[0] Isolate a portion of the larger Gremlin
statement for analysis. The isolated portion
should be only as long as you are capable of
following by just reading the code.
Isolate for Analysis 1
© 2018. All Rights Reserved.
Be clear on the result being returned from the
current portion of Gremlin under review as it will
feed into the following steps that will later be
analyzed.
Clarify Results 2
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> valueMap()
==>[name:[alice]]
Be clear on the result being returned from the
current portion of Gremlin under review as it
will feed into the following steps that will later
be analyzed.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Clarify Results 2
© 2018. All Rights Reserved.
If using DataStax Studio, consider converting
results containing vertices to incident edges,
using inE(), outE() or bothE(), which will allow
for a graph visualization of the result.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Clarify Results 2
© 2018. All Rights Reserved.
Validate any assumptions regarding the nature
of the traversal. Consider the traversal path,
side-effects, the graph schema or anything that
might be hidden by a naive view of the result.
Validate Assumptions 3
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> path().next()
==>v[0]
==>e[10][0-rates->2]
==>v[2]
==>e[11][2-rates->4]
==>v[4]
==>e[12][4-rates->6]
==>v[6]
==>e[13][6-rates->8]
==>v[8]
==>e[14][8-rates->0]
==>v[0]
Validate any assumptions regarding the nature
of the traversal. Consider the traversal path,
the graph schema or anything that might be
hidden by a naive view of the result.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Validate Assumptions 3
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> select('v')
==>[v[0],v[2],v[4],v[6],v[8],v[0]]
Step labels - created with as()-step - are a
type of side-effect. Have clarity in terms of
what they contain. Use select()-step to extract
their contents.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Validate Assumptions 3
© 2018. All Rights Reserved.
Isolate for
Analysis
1
Validate
Assumptions
3
● Use values() or valueMap()
for vertex/edge results
● Visualize results
● Use path() to inspect what
has been traversed
● Inspect step labels with
select()
Clarify
Results
2
© 2018. All Rights Reserved.
Slowly expand the portion of Gremlin being
analyzed to the next point of isolation and repeat
the debugging cycle.
Isolate for Analysis 1
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name')
==>v[0]
Slowly expand the portion of Gremlin being
analyzed to the next point of isolation and
repeat the debugging cycle.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Isolate for Analysis 1
© 2018. All Rights Reserved.
Isolate for
Analysis
1
Validate
Assumptions
3
● Use values() or valueMap()
for vertex/edge results
● Visualize results
● Use path() to inspect what
has been traversed
● Inspect step labels with
select()
● Inspect contents of side-
effects steps with cap()
Clarify
Results
2
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> cap('a')
==>[alice]
As with step labels, verify the contents of side-
effects. In this case, determine what is being
stored in the "a" side-effect by using cap()-
step.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Examine Side-effects 3
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold())
==>v[0]
Slowly expand the portion of Gremlin being
analyzed to the next point of isolation and
repeat the debugging cycle.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Isolate for Analysis 1
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> cap('a')
==>[alice,[alice,bobby,cindy,david,eliza,alice]]
As with step labels, verify the contents of side-
effects. In this case, determine what is being
stored in the "a" side-effect by using cap()-
step.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Examine Side-effects 3
© 2018. All Rights Reserved.
Isolate for
Analysis
1
Validate
Assumptions
3
● Use values() or valueMap()
for vertex/edge results
● Visualize results
● Use path() to inspect what
has been traversed
● Inspect step labels with
select()
● Inspect contents of side-
effects steps with cap()
Clarify
Results
2
● Large or complex
anonymous traversals may
require their own isolated
analysis
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v')).
......7> cap('a')
==>[alice,[v[0],v[2],v[4],v[6],v[8],v[0]]]
To gain clarity on anonymous traversals,
isolate them for review as part of the
debugging cycle.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Isolate for Analysis 1
© 2018. All Rights Reserved.
Isolate for
Analysis
1
Validate
Assumptions
3
● Use values() or valueMap()
for vertex/edge results
● Visualize results
● Consider temporarily
promoting an anonymous
traversal to its parent if it
yields better clarity into the
result
● Use path() to inspect what
has been traversed
● Inspect step labels with
select()
● Inspect contents of side-
effects steps with cap()
Clarify
Results
2
● Large or complex anonymous
traversals may require their
own isolated analysis
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> select(all, 'v')
==>[v[0],v[2],v[4],v[6],v[8],v[0]]
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> select(all, 'v').
......4> unfold().
......5> values('name')
==>alice
==>bobby
==>cindy
==>david
==>eliza
==>alice
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> select(all, 'v').
......4> unfold().
......5> values('name').
......6> fold()
==>[alice,bobby,cindy,david,eliza,alice]
For analysis consider temporarily promoting
the anonymous traversal to the parent
traversal as it might allow better focus on the
actual result. In this case, the store() side-
effects are not relevant to the specific analysis
of the contents of the by() modulator.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Clarify Results 2A
B
C
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold()).
.....15> unfold().
.....16> sack(assign).
.....17> by(constant(1d)).
.....18> sack(div).
.....19> by(union(constant(1d),
.....20> tail(local, 1)).sum()).
.....21> sack(mult).
.....22> by(limit(local, 1)).
.....23> sack().sum()).
.....24> cap('a')
==>[alice,[alice,bobby,cindy,david,eliza,alice],[9,8,7,6,10],18.833333333333332]
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold())).
.....15> cap('a').next()
==>alice
==>[alice,bobby,cindy,david,eliza,alice]
==>[9,8,7,6,10]
==>[[9,0],[8,1],[7,2],[6,3],[10,4]]
It may be necessary to isolate anonymous
traversals if they are especially complex.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Isolate for Analysis 1
© 2018. All Rights Reserved.
Isolate for
Analysis
1
Validate
Assumptions
3
● Use values() or valueMap()
for vertex/edge results
● Visualize results
● Consider temporarily
promoting an anonymous
traversal to its parent if it
yields better clarity into the
result
● Use path() to inspect what
has been traversed
● Inspect step labels with
select()
● Inspect contents of side-
effects steps with cap()
Clarify
Results
2
● Large or complex anonymous
traversals may require their
own isolated analysis
● Isolation within an
anonymous traversal can
produce misleading
intermediate results -
including the end portion of
a traversal may be helpful
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold()).
.....15> unfold()).
.....16> cap('a').next()
==>alice
==>[alice,bobby,cindy,david,eliza,alice]
==>[9,8,7,6,10]
==>[9,0]
Analyzing portions of a traversal can produce
misleading intermediate results that might
leave an incorrect impression as to the overall
intention of the traversal when executed as a
whole.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Isolate for Analysis 1
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold()).
.....15> unfold().
.....16> sack(assign).
.....17> by(constant(1d))).
.....18> cap('a').next()
==>alice
==>[alice,bobby,cindy,david,eliza,alice]
==>[9,8,7,6,10]
==>[9,0]
Analyzing portions of a traversal can produce
misleading intermediate results that might
leave an incorrect impression as to the overall
intention of the traversal when executed as a
whole.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Isolate for Analysis 1
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold()).
.....15> unfold().
.....16> sack(assign).
.....17> by(constant(1d)).
.....18> sack().sum()).
.....19> cap('a').next()
==>alice
==>[alice,bobby,cindy,david,eliza,alice]
==>[9,8,7,6,10]
==>5.0
Include context from the end of a portion of a
traversal to help ensure the intent of the
overall traversal is consistent.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Isolate for Analysis 1
© 2018. All Rights Reserved.
Isolate for
Analysis
1
Validate
Assumptions
3
● Use values() or valueMap()
for vertex/edge results
● Visualize results
● Consider temporarily
promoting an anonymous
traversal to its parent if it
yields better clarity into the
result
● fold() can be a good
temporary replacement for
other reducing steps like
sum(), max(), min(), etc. as
it provides visibility to the
values of that computation
● Use path() to inspect what
has been traversed
● Inspect step labels with
select()
● Inspect contents of side-
effects steps with cap()
Clarify
Results
2
● Large or complex anonymous
traversals may require their
own isolated analysis
● Isolation within an anonymous
traversal can produce
misleading intermediate
results - including the end
portion of a traversal may be
helpful
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold()).
.....15> unfold().
.....16> sack(assign).
.....17> by(constant(1d)).
.....18> sack().fold()).
.....19> cap('a').next()
==>alice
==>[alice,bobby,cindy,david,eliza,alice]
==>[9,8,7,6,10]
==>[1.0,1.0,1.0,1.0,1.0]
Do not allow the actual steps in the traversal to
prevent visibility into the nature of the
computations that Gremlin is performing.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Clarify Results 2
© 2018. All Rights Reserved.
Isolate for
Analysis
1
Validate
Assumptions
3
● Use values() or valueMap()
for vertex/edge results
● Visualize results
● Consider temporarily
promoting an anonymous
traversal to its parent if it
yields better clarity into the
result
● fold() can be a good
temporary replacement for
other reducing steps like
sum(), max(), min(), etc. as it
provides visibility to the values
of that computation
● Isolate results of interest
● Use path() to inspect what
has been traversed
● Inspect step labels with
select()
● Inspect contents of side-
effects steps with cap()
Clarify
Results
2
● Large or complex anonymous
traversals may require their
own isolated analysis
● Isolation within an anonymous
traversal can produce
misleading intermediate
results - including the end
portion of a traversal may be
helpful
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold()).
.....15> unfold().
.....16> sack(assign).
.....17> by(constant(1d)).
.....18> sack(div).
.....19> by(union(constant(1d),
.....20> tail(local, 1)).sum()).
.....21> sack().fold()).
.....22> cap('a').unfold().skip(3).fold().next()
==>[1.0,0.5,0.3333333333333333,0.25,0.2]
Limit output as necessary to focus on the
aspects of the results that are most under
consideration.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Clarify Results 2
© 2018. All Rights Reserved.
Isolate for
Analysis
1
Validate
Assumptions
3
● Use values() or valueMap()
for vertex/edge results
● Visualize results
● Consider temporarily
promoting an anonymous
traversal to its parent if it
yields better clarity into the
result
● fold() can be a good
temporary replacement for
other reducing steps like
sum(), max(), min(), etc. as it
provides visibility to the values
of that computation
● Isolate results of interest
● Use path() to inspect what
has been traversed
● Inspect step labels with
select()
● Inspect contents of side-
effects steps with cap()
Clarify
Results
2
● Large or complex anonymous
traversals may require their
own isolated analysis
● Isolation within an anonymous
traversal can produce
misleading intermediate
results - including the end
portion of a traversal may be
helpful
● Simulate a traversal from a
specific known input with
the inject() start step
© 2018. All Rights Reserved.
gremlin> g.inject([9,0],[8,1],[7,2],[6,3],[10,4]).
......1> sack(assign).
......2> by(constant(1d)).
......3> sack(div).
......4> by(union(constant(1d),tail(local,1)).sum()).
......5> sack()
==>1.0
==>0.5
==>0.3333333333333333
==>0.25
==>0.2
gremlin> g.inject([10,4]).
......1> union(constant(1d),tail(local,1))
==>1.0
==>4
gremlin> g.inject([10,4]).
......1> union(constant(1d),tail(local,1)).
......2> sum()
==>5.0
gremlin> 1.0d / g.inject([10,4]).
......1> union(constant(1d),tail(local,1)).
......2> sum().next()
==>0.2
Lost? Reclaim focus by simulating just the
portion of the traversal that is not yet
understood.
g.V().has('name','alice').as('v').
repeat(outE().as('e').inV().as('v')).
until(has('name','alice')).
store('a').
by('name').
store('a').
by(select(all, 'v').unfold().values('name').fold()).
store('a').
by(select(all, 'e').unfold().
store('x').
by(union(values('value'),
select('x').count(local)).fold()).
cap('x').
store('a').
by(unfold().limit(local, 1).fold()).
unfold().
sack(assign).
by(constant(1d)).
sack(div).
by(union(constant(1d),
tail(local, 1)).sum()).
sack(mult).
by(limit(local, 1)).
sack().sum()).
cap('a')
Isolate for Analysis 1
B
A
C
D
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold()).
.....15> unfold().
.....16> sack(assign).
.....17> by(constant(1d)).
.....18> sack(div).
.....19> by(union(constant(1d),
.....20> tail(local, 1)).sum()).
.....21> sack(mult).
.....22> by(limit(local, 1)).
.....23> sack().sum()).
.....24> cap('a')
==>[alice,[alice,bobby,cindy,david,eliza,alice],[9,8,7,6,10],18.833333333333332]
© 2018. All Rights Reserved.
gremlin> g.V().has('name','alice').as('v').
......1> repeat(outE().as('e').inV().as('v')).
......2> until(has('name','alice')).
......3> store('a').
......4> by('name').
......5> store('a').
......6> by(select(all, 'v').unfold().values('name').fold()).
......7> store('a').
......8> by(select(all, 'e').unfold().
......9> store('x').
.....10> by(union(values('value'),
.....11> select('x').count(local)).fold()).
.....12> cap('x').
.....13> store('a').
.....14> by(unfold().limit(local, 1).fold()).
.....15> unfold().
.....16> sack(assign).
.....17> by(constant(1d)).
.....18> sack(div).
.....19> by(union(constant(1d),
.....20> tail(local, 1)).sum()).
.....21> sack(mult).
.....22> by(limit(local, 1)).
.....23> sack().sum()).
.....24> cap('a')
==>[alice,[alice,bobby,cindy,david,eliza,alice],[9,8,7,6,10],18.833333333333332]
Overriding traversers with by()-
modulators
Creating indexed values
Using sack() for computations
Result construction with side-effects
Methods of cycle-detection
Traversal patterns identified as a result
of Gremlin Debugging Cycle
Step label access and collection
manipulation
© 2018. All Rights Reserved.
Isolate for
Analysis
1
Validate
Assumptions
3
● Use values() or valueMap()
for vertex/edge results
● Visualize results
● Consider temporarily
promoting an anonymous
traversal to its parent if it
yields better clarity into the
result
● fold() can be a good
temporary replacement for
other reducing steps like
sum(), max(), min(), etc. as it
provides visibility to the values
of that computation
● Isolate results of interest
● Use path() to inspect what
has been traversed
● Inspect step labels with
select()
● Inspect contents of side-
effects steps with cap()
Clarify
Results
2
● Large or complex anonymous
traversals may require their
own isolated analysis
● Isolation within an anonymous
traversal can produce
misleading intermediate
results - including the end
portion of a traversal may be
helpful
● Simulate a traversal from a
specific known input with the
inject() start step
© 2018. All Rights Reserved.
What's next?
© 2017. All Rights Reserved.
● Apache TinkerPop Website
○ http://tinkerpop.apache.org/
● Gremlin Recipes
○ http://tinkerpop.apache.org/docs/current/recipes/
● The Gremlin Compendium
○ http://www.doanduyhai.com/blog/?p=13460
● Practical Gremlin
○ http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html
● Gremlin DSLs - Part I
○ https://www.datastax.com/dev/blog/gremlin-dsls-in-java-with-dse-graph
● Gremlin DSLs - Part II
○ https://academy.datastax.com/content/gremlin-dsls-python-dse-graph
Resources
1 of 56

Recommended

Gremlin's Graph Traversal Machinery by
Gremlin's Graph Traversal MachineryGremlin's Graph Traversal Machinery
Gremlin's Graph Traversal MachineryMarko Rodriguez
8.3K views85 slides
ACM DBPL Keynote: The Graph Traversal Machine and Language by
ACM DBPL Keynote: The Graph Traversal Machine and LanguageACM DBPL Keynote: The Graph Traversal Machine and Language
ACM DBPL Keynote: The Graph Traversal Machine and LanguageMarko Rodriguez
9.4K views140 slides
Graph Partition with Natural Cuts by
Graph Partition with Natural CutsGraph Partition with Natural Cuts
Graph Partition with Natural Cutsilyaraz
1.8K views47 slides
Extending Gremlin with Foundational Steps by
Extending Gremlin with Foundational StepsExtending Gremlin with Foundational Steps
Extending Gremlin with Foundational StepsStephen Mallette
1.1K views54 slides
The Gremlin Graph Traversal Language by
The Gremlin Graph Traversal LanguageThe Gremlin Graph Traversal Language
The Gremlin Graph Traversal LanguageMarko Rodriguez
21.4K views50 slides
Neptune, the Graph Database | AWS Floor28 by
Neptune, the Graph Database | AWS Floor28Neptune, the Graph Database | AWS Floor28
Neptune, the Graph Database | AWS Floor28Amazon Web Services
1.1K views38 slides

More Related Content

What's hot

Graph and Amazon Neptune by
Graph and Amazon NeptuneGraph and Amazon Neptune
Graph and Amazon NeptuneAmazon Web Services
1.1K views50 slides
Gremlin: A Graph-Based Programming Language by
Gremlin: A Graph-Based Programming LanguageGremlin: A Graph-Based Programming Language
Gremlin: A Graph-Based Programming LanguageMarko Rodriguez
28.7K views60 slides
Be Smart, Constrain Your Types to Free Your Brain! by
Be Smart, Constrain Your Types to Free Your Brain!Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!Jorge Vásquez
970 views178 slides
Apache Flink Stream Processing by
Apache Flink Stream ProcessingApache Flink Stream Processing
Apache Flink Stream ProcessingSuneel Marthi
1.4K views43 slides
ClickHouse Features for Advanced Users, by Aleksei Milovidov by
ClickHouse Features for Advanced Users, by Aleksei MilovidovClickHouse Features for Advanced Users, by Aleksei Milovidov
ClickHouse Features for Advanced Users, by Aleksei MilovidovAltinity Ltd
8.4K views39 slides
TinkerPop 2020 by
TinkerPop 2020TinkerPop 2020
TinkerPop 2020Joshua Shinavier
966 views42 slides

What's hot(20)

Gremlin: A Graph-Based Programming Language by Marko Rodriguez
Gremlin: A Graph-Based Programming LanguageGremlin: A Graph-Based Programming Language
Gremlin: A Graph-Based Programming Language
Marko Rodriguez28.7K views
Be Smart, Constrain Your Types to Free Your Brain! by Jorge Vásquez
Be Smart, Constrain Your Types to Free Your Brain!Be Smart, Constrain Your Types to Free Your Brain!
Be Smart, Constrain Your Types to Free Your Brain!
Jorge Vásquez970 views
Apache Flink Stream Processing by Suneel Marthi
Apache Flink Stream ProcessingApache Flink Stream Processing
Apache Flink Stream Processing
Suneel Marthi1.4K views
ClickHouse Features for Advanced Users, by Aleksei Milovidov by Altinity Ltd
ClickHouse Features for Advanced Users, by Aleksei MilovidovClickHouse Features for Advanced Users, by Aleksei Milovidov
ClickHouse Features for Advanced Users, by Aleksei Milovidov
Altinity Ltd8.4K views
Capabilities for Resources and Effects by Martin Odersky
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
Martin Odersky5.5K views
HTTP Analytics for 6M requests per second using ClickHouse, by Alexander Boc... by Altinity Ltd
HTTP Analytics for 6M requests per second using ClickHouse, by  Alexander Boc...HTTP Analytics for 6M requests per second using ClickHouse, by  Alexander Boc...
HTTP Analytics for 6M requests per second using ClickHouse, by Alexander Boc...
Altinity Ltd3.5K views
Transpilers Gone Wild: Introducing Hydra by Joshua Shinavier
Transpilers Gone Wild: Introducing HydraTranspilers Gone Wild: Introducing Hydra
Transpilers Gone Wild: Introducing Hydra
Joshua Shinavier593 views
Hive Tutorial | Hive Architecture | Hive Tutorial For Beginners | Hive In Had... by Simplilearn
Hive Tutorial | Hive Architecture | Hive Tutorial For Beginners | Hive In Had...Hive Tutorial | Hive Architecture | Hive Tutorial For Beginners | Hive In Had...
Hive Tutorial | Hive Architecture | Hive Tutorial For Beginners | Hive In Had...
Simplilearn3.9K views
Apache Calcite overview by Julian Hyde
Apache Calcite overviewApache Calcite overview
Apache Calcite overview
Julian Hyde19.5K views
Presto: Distributed sql query engine by kiran palaka
Presto: Distributed sql query engine Presto: Distributed sql query engine
Presto: Distributed sql query engine
kiran palaka9.6K views
Introducing DataFrames in Spark for Large Scale Data Science by Databricks
Introducing DataFrames in Spark for Large Scale Data ScienceIntroducing DataFrames in Spark for Large Scale Data Science
Introducing DataFrames in Spark for Large Scale Data Science
Databricks41K views
Introduction to Redis by Arnab Mitra
Introduction to RedisIntroduction to Redis
Introduction to Redis
Arnab Mitra11.1K views
An overview of Neo4j Internals by Tobias Lindaaker
An overview of Neo4j InternalsAn overview of Neo4j Internals
An overview of Neo4j Internals
Tobias Lindaaker48.9K views
Working with JSON Data in PostgreSQL vs. MongoDB by ScaleGrid.io
Working with JSON Data in PostgreSQL vs. MongoDBWorking with JSON Data in PostgreSQL vs. MongoDB
Working with JSON Data in PostgreSQL vs. MongoDB
ScaleGrid.io830 views
Webinar: Working with Graph Data in MongoDB by MongoDB
Webinar: Working with Graph Data in MongoDBWebinar: Working with Graph Data in MongoDB
Webinar: Working with Graph Data in MongoDB
MongoDB29K views
The Apache Spark File Format Ecosystem by Databricks
The Apache Spark File Format EcosystemThe Apache Spark File Format Ecosystem
The Apache Spark File Format Ecosystem
Databricks2.1K views
Building Applications with a Graph Database by Tobias Lindaaker
Building Applications with a Graph DatabaseBuilding Applications with a Graph Database
Building Applications with a Graph Database
Tobias Lindaaker4.3K views

Similar to Gremlin's Anatomy

A well-typed program never goes wrong by
A well-typed program never goes wrongA well-typed program never goes wrong
A well-typed program never goes wrongJulien Wetterwald
2.4K views47 slides
Introduction To Scala by
Introduction To ScalaIntroduction To Scala
Introduction To ScalaPeter Maas
1.6K views21 slides
C tutorial by
C tutorialC tutorial
C tutorialPatruni Chidananda Sastry
143 views61 slides
Python Workshop. LUG Maniapl by
Python Workshop. LUG ManiaplPython Workshop. LUG Maniapl
Python Workshop. LUG ManiaplAnkur Shrivastava
570 views44 slides
Matlab Basic Tutorial by
Matlab Basic TutorialMatlab Basic Tutorial
Matlab Basic TutorialMuhammad Rizwan
21K views52 slides
Evolving The Java Language by
Evolving The Java LanguageEvolving The Java Language
Evolving The Java LanguageQConLondon2008
424 views42 slides

Similar to Gremlin's Anatomy(20)

A well-typed program never goes wrong by Julien Wetterwald
A well-typed program never goes wrongA well-typed program never goes wrong
A well-typed program never goes wrong
Julien Wetterwald2.4K views
Introduction To Scala by Peter Maas
Introduction To ScalaIntroduction To Scala
Introduction To Scala
Peter Maas1.6K views
Scala as a Declarative Language by vsssuresh
Scala as a Declarative LanguageScala as a Declarative Language
Scala as a Declarative Language
vsssuresh3.2K views
Developing Your Own Flux Packages by David McKay | Head of Developer Relation... by InfluxData
Developing Your Own Flux Packages by David McKay | Head of Developer Relation...Developing Your Own Flux Packages by David McKay | Head of Developer Relation...
Developing Your Own Flux Packages by David McKay | Head of Developer Relation...
InfluxData155 views
Introduction To Groovy 2005 by Tugdual Grall
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005
Tugdual Grall856 views
Functional programming-advantages by Sergei Winitzki
Functional programming-advantagesFunctional programming-advantages
Functional programming-advantages
Sergei Winitzki129 views
C Programming by Adil Jafri
C ProgrammingC Programming
C Programming
Adil Jafri4.6K views
javasebeyondbasics by webuploader
javasebeyondbasicsjavasebeyondbasics
javasebeyondbasics
webuploader1.2K views
Jscript Fundamentals by rspaike
Jscript FundamentalsJscript Fundamentals
Jscript Fundamentals
rspaike621 views
Introduction To TensorFlow | Deep Learning Using TensorFlow | TensorFlow Tuto... by Edureka!
Introduction To TensorFlow | Deep Learning Using TensorFlow | TensorFlow Tuto...Introduction To TensorFlow | Deep Learning Using TensorFlow | TensorFlow Tuto...
Introduction To TensorFlow | Deep Learning Using TensorFlow | TensorFlow Tuto...
Edureka!6.8K views
SeaJUG March 2004 - Groovy by Ted Leung
SeaJUG March 2004 - GroovySeaJUG March 2004 - Groovy
SeaJUG March 2004 - Groovy
Ted Leung591 views

Recently uploaded

Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or... by
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...ShapeBlue
199 views20 slides
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ... by
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...ShapeBlue
129 views10 slides
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading... by
Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading...The Digital Insurer
91 views52 slides
The Power of Heat Decarbonisation Plans in the Built Environment by
The Power of Heat Decarbonisation Plans in the Built EnvironmentThe Power of Heat Decarbonisation Plans in the Built Environment
The Power of Heat Decarbonisation Plans in the Built EnvironmentIES VE
84 views20 slides
"Running students' code in isolation. The hard way", Yurii Holiuk by
"Running students' code in isolation. The hard way", Yurii Holiuk "Running students' code in isolation. The hard way", Yurii Holiuk
"Running students' code in isolation. The hard way", Yurii Holiuk Fwdays
36 views34 slides
The Power of Generative AI in Accelerating No Code Adoption.pdf by
The Power of Generative AI in Accelerating No Code Adoption.pdfThe Power of Generative AI in Accelerating No Code Adoption.pdf
The Power of Generative AI in Accelerating No Code Adoption.pdfSaeed Al Dhaheri
39 views18 slides

Recently uploaded(20)

Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or... by ShapeBlue
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...
Zero to Cloud Hero: Crafting a Private Cloud from Scratch with XCP-ng, Xen Or...
ShapeBlue199 views
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ... by ShapeBlue
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
Live Demo Showcase: Unveiling Dell PowerFlex’s IaaS Capabilities with Apache ...
ShapeBlue129 views
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading... by The Digital Insurer
Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...Webinar : Desperately Seeking Transformation - Part 2:  Insights from leading...
Webinar : Desperately Seeking Transformation - Part 2: Insights from leading...
The Power of Heat Decarbonisation Plans in the Built Environment by IES VE
The Power of Heat Decarbonisation Plans in the Built EnvironmentThe Power of Heat Decarbonisation Plans in the Built Environment
The Power of Heat Decarbonisation Plans in the Built Environment
IES VE84 views
"Running students' code in isolation. The hard way", Yurii Holiuk by Fwdays
"Running students' code in isolation. The hard way", Yurii Holiuk "Running students' code in isolation. The hard way", Yurii Holiuk
"Running students' code in isolation. The hard way", Yurii Holiuk
Fwdays36 views
The Power of Generative AI in Accelerating No Code Adoption.pdf by Saeed Al Dhaheri
The Power of Generative AI in Accelerating No Code Adoption.pdfThe Power of Generative AI in Accelerating No Code Adoption.pdf
The Power of Generative AI in Accelerating No Code Adoption.pdf
Saeed Al Dhaheri39 views
"Surviving highload with Node.js", Andrii Shumada by Fwdays
"Surviving highload with Node.js", Andrii Shumada "Surviving highload with Node.js", Andrii Shumada
"Surviving highload with Node.js", Andrii Shumada
Fwdays58 views
Initiating and Advancing Your Strategic GIS Governance Strategy by Safe Software
Initiating and Advancing Your Strategic GIS Governance StrategyInitiating and Advancing Your Strategic GIS Governance Strategy
Initiating and Advancing Your Strategic GIS Governance Strategy
Safe Software184 views
State of the Union - Rohit Yadav - Apache CloudStack by ShapeBlue
State of the Union - Rohit Yadav - Apache CloudStackState of the Union - Rohit Yadav - Apache CloudStack
State of the Union - Rohit Yadav - Apache CloudStack
ShapeBlue303 views
Future of AR - Facebook Presentation by Rob McCarty
Future of AR - Facebook PresentationFuture of AR - Facebook Presentation
Future of AR - Facebook Presentation
Rob McCarty65 views
Don’t Make A Human Do A Robot’s Job! : 6 Reasons Why AI Will Save Us & Not De... by Moses Kemibaro
Don’t Make A Human Do A Robot’s Job! : 6 Reasons Why AI Will Save Us & Not De...Don’t Make A Human Do A Robot’s Job! : 6 Reasons Why AI Will Save Us & Not De...
Don’t Make A Human Do A Robot’s Job! : 6 Reasons Why AI Will Save Us & Not De...
Moses Kemibaro35 views
LLMs in Production: Tooling, Process, and Team Structure by Aggregage
LLMs in Production: Tooling, Process, and Team StructureLLMs in Production: Tooling, Process, and Team Structure
LLMs in Production: Tooling, Process, and Team Structure
Aggregage57 views
CloudStack Managed User Data and Demo - Harikrishna Patnala - ShapeBlue by ShapeBlue
CloudStack Managed User Data and Demo - Harikrishna Patnala - ShapeBlueCloudStack Managed User Data and Demo - Harikrishna Patnala - ShapeBlue
CloudStack Managed User Data and Demo - Harikrishna Patnala - ShapeBlue
ShapeBlue137 views
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online by ShapeBlue
KVM Security Groups Under the Hood - Wido den Hollander - Your.OnlineKVM Security Groups Under the Hood - Wido den Hollander - Your.Online
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online
ShapeBlue225 views
The Role of Patterns in the Era of Large Language Models by Yunyao Li
The Role of Patterns in the Era of Large Language ModelsThe Role of Patterns in the Era of Large Language Models
The Role of Patterns in the Era of Large Language Models
Yunyao Li91 views
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit... by ShapeBlue
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...
ShapeBlue162 views
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R... by ShapeBlue
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...
Setting Up Your First CloudStack Environment with Beginners Challenges - MD R...
ShapeBlue178 views
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue by ShapeBlue
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlueCloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue
CloudStack Object Storage - An Introduction - Vladimir Petrov - ShapeBlue
ShapeBlue139 views

Gremlin's Anatomy

  • 2. © 2018. All Rights Reserved. What is a graph?
  • 3. © 2018. All Rights Reserved. ● A property graph is a collection of vertices and edges ○ A vertex represents entities/domain objects ○ An edge represents a directional relationship between two vertices ○ Vertices and edges have labels and properties label: person name: Stephen label: company name: DataStax label: person name: Paras label: employs since: 2015 label: employs since: 2016 label: knows
  • 4. © 2018. All Rights Reserved. How does Apache TinkerPop support graph processing?
  • 5. © 2018. All Rights Reserved.
  • 6. © 2018. All Rights Reserved. Gremlin's Anatomy refers to the study of the Gremlin graph traversal language at a level beyond just reference to the set of steps that define the language itself.
  • 7. © 2018. All Rights Reserved. ● Reasons to study Gremlin's Anatomy ○ Write better Gremlin ○ Improve ability to read more complex Gremlin ○ Ask more concise questions if you get stuck ○ Develop more robust and expressive Domain Specific Languages
  • 8. © 2018. All Rights Reserved. g.V() GraphTraversalSource ● Spawns GraphTraversal instances with start steps ● Holds configurations that Gremlin will use in the traversal
  • 9. © 2018. All Rights Reserved. g.V(). has('movie', 'title', 'Young Guns'). outE(). groupCount() GraphTraversal ● The steps that make up the Gremlin language ● Each step returns a GraphTraversal so that steps can be chained together ● The output of one step becomes the input to the next
  • 10. © 2018. All Rights Reserved. g.V(). has('movie', 'title', 'Young Guns'). outE(). groupCount(). by() Step Modulators ● Step modulators look back on the previous step and modifies their behavior
  • 11. © 2018. All Rights Reserved. g.V(). has('movie', 'title', 'Young Guns'). outE(). groupCount(). by(label()) Anonymous Traversal ● A traversal not bound to a GraphTraversalSource ● Spawned from the double underscore class (e.g __.label()) ● Usually exposed as standalone functions for better readability
  • 12. © 2018. All Rights Reserved. g.V(). has('movie', 'title', within('Young Guns', 'Hot Shots!')). outE(). groupCount(). by(label()) Expressions ● Typically refers to string tokens, enums or Predicate values (i.e. anything that makes Gremlin more readable) ● Be aware of naming collisions with steps and other expressions (e.g. P.not() and not() step).
  • 13. © 2018. All Rights Reserved. g.V(). has('movie', 'title', within('Young Guns', 'Hot Shots!')). outE(). groupCount(). by(label()).next() Terminal Steps ● Steps that do not return a traversal and instead return the traversal result. ● Commonly used terminal steps include hasNext(), next(), iterate(), toList(). ● If you don't have a terminal step, you don't have a result. You just have a GraphTraversal.
  • 14. © 2018. All Rights Reserved. The Gremlin Debugging Cycle presents methods and techniques that provide insight into Gremlin statements of any complexity for purposes of learning, debugging, and crafting traversals.
  • 15. © 2018. All Rights Reserved. https://stackoverflow.com/a/47680050/1831717 g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a')
  • 16. label: rates tag: ruby value: 8 label: rates tag: ruby value: 9 © 2018. All Rights Reserved. Sample Graph name: alice name: bobby name: cindy label: rates tag: ruby value: 7 name: david label: rates tag: ruby value: 6 name: eliza label: rates tag: java value: 10
  • 17. © 2018. All Rights Reserved. ,,,/ (o o) -----oOOo-(3)-oOOo----- plugin activated: tinkerpop.server plugin activated: tinkerpop.utilities plugin activated: tinkerpop.tinkergraph gremlin>
  • 18. © 2018. All Rights Reserved. gremlin> graph = TinkerGraph.open() ==>tinkergraph[vertices:0 edges:0] gremlin> g = graph.traversal() ==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard] gremlin> g.addV().property('name','alice').as('a'). ......1> addV().property('name','bobby').as('b'). ......2> addV().property('name','cindy').as('c'). ......3> addV().property('name','david').as('d'). ......4> addV().property('name','eliza').as('e'). ......5> addE('rates').from('a').to('b').property('tag','ruby').property('value',9). ......6> addE('rates').from('b').to('c').property('tag','ruby').property('value',8). ......7> addE('rates').from('c').to('d').property('tag','ruby').property('value',7). ......8> addE('rates').from('d').to('e').property('tag','ruby').property('value',6). ......9> addE('rates').from('e').to('a').property('tag','java').property('value',10). .....10> iterate() gremlin> graph ==>tinkergraph[vertices:5 edges:5]
  • 19. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold()). .....15> unfold(). .....16> sack(assign). .....17> by(constant(1d)). .....18> sack(div). .....19> by(union(constant(1d), .....20> tail(local, 1)).sum()). .....21> sack(mult). .....22> by(limit(local, 1)). .....23> sack().sum()). .....24> cap('a') ==>[alice,[alice,bobby,cindy,david,eliza,alice],[9,8,7,6,10],18.833333333333332]
  • 20. © 2018. All Rights Reserved. Isolate for Analysis Clarify Results Validate Assumptions 1 23 Gremlin Debugging Cycle
  • 21. © 2018. All Rights Reserved. Isolate a portion of the larger Gremlin statement for analysis. The isolated portion should be only as long as you are capable of following by just reading the code. Isolate for Analysis 1
  • 22. © 2018. All Rights Reserved. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')) ==>v[0] Isolate a portion of the larger Gremlin statement for analysis. The isolated portion should be only as long as you are capable of following by just reading the code. Isolate for Analysis 1
  • 23. © 2018. All Rights Reserved. Be clear on the result being returned from the current portion of Gremlin under review as it will feed into the following steps that will later be analyzed. Clarify Results 2
  • 24. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> valueMap() ==>[name:[alice]] Be clear on the result being returned from the current portion of Gremlin under review as it will feed into the following steps that will later be analyzed. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Clarify Results 2
  • 25. © 2018. All Rights Reserved. If using DataStax Studio, consider converting results containing vertices to incident edges, using inE(), outE() or bothE(), which will allow for a graph visualization of the result. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Clarify Results 2
  • 26. © 2018. All Rights Reserved. Validate any assumptions regarding the nature of the traversal. Consider the traversal path, side-effects, the graph schema or anything that might be hidden by a naive view of the result. Validate Assumptions 3
  • 27. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> path().next() ==>v[0] ==>e[10][0-rates->2] ==>v[2] ==>e[11][2-rates->4] ==>v[4] ==>e[12][4-rates->6] ==>v[6] ==>e[13][6-rates->8] ==>v[8] ==>e[14][8-rates->0] ==>v[0] Validate any assumptions regarding the nature of the traversal. Consider the traversal path, the graph schema or anything that might be hidden by a naive view of the result. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Validate Assumptions 3
  • 28. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> select('v') ==>[v[0],v[2],v[4],v[6],v[8],v[0]] Step labels - created with as()-step - are a type of side-effect. Have clarity in terms of what they contain. Use select()-step to extract their contents. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Validate Assumptions 3
  • 29. © 2018. All Rights Reserved. Isolate for Analysis 1 Validate Assumptions 3 ● Use values() or valueMap() for vertex/edge results ● Visualize results ● Use path() to inspect what has been traversed ● Inspect step labels with select() Clarify Results 2
  • 30. © 2018. All Rights Reserved. Slowly expand the portion of Gremlin being analyzed to the next point of isolation and repeat the debugging cycle. Isolate for Analysis 1
  • 31. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name') ==>v[0] Slowly expand the portion of Gremlin being analyzed to the next point of isolation and repeat the debugging cycle. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Isolate for Analysis 1
  • 32. © 2018. All Rights Reserved. Isolate for Analysis 1 Validate Assumptions 3 ● Use values() or valueMap() for vertex/edge results ● Visualize results ● Use path() to inspect what has been traversed ● Inspect step labels with select() ● Inspect contents of side- effects steps with cap() Clarify Results 2
  • 33. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> cap('a') ==>[alice] As with step labels, verify the contents of side- effects. In this case, determine what is being stored in the "a" side-effect by using cap()- step. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Examine Side-effects 3
  • 34. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()) ==>v[0] Slowly expand the portion of Gremlin being analyzed to the next point of isolation and repeat the debugging cycle. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Isolate for Analysis 1
  • 35. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> cap('a') ==>[alice,[alice,bobby,cindy,david,eliza,alice]] As with step labels, verify the contents of side- effects. In this case, determine what is being stored in the "a" side-effect by using cap()- step. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Examine Side-effects 3
  • 36. © 2018. All Rights Reserved. Isolate for Analysis 1 Validate Assumptions 3 ● Use values() or valueMap() for vertex/edge results ● Visualize results ● Use path() to inspect what has been traversed ● Inspect step labels with select() ● Inspect contents of side- effects steps with cap() Clarify Results 2 ● Large or complex anonymous traversals may require their own isolated analysis
  • 37. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v')). ......7> cap('a') ==>[alice,[v[0],v[2],v[4],v[6],v[8],v[0]]] To gain clarity on anonymous traversals, isolate them for review as part of the debugging cycle. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Isolate for Analysis 1
  • 38. © 2018. All Rights Reserved. Isolate for Analysis 1 Validate Assumptions 3 ● Use values() or valueMap() for vertex/edge results ● Visualize results ● Consider temporarily promoting an anonymous traversal to its parent if it yields better clarity into the result ● Use path() to inspect what has been traversed ● Inspect step labels with select() ● Inspect contents of side- effects steps with cap() Clarify Results 2 ● Large or complex anonymous traversals may require their own isolated analysis
  • 39. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> select(all, 'v') ==>[v[0],v[2],v[4],v[6],v[8],v[0]] gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> select(all, 'v'). ......4> unfold(). ......5> values('name') ==>alice ==>bobby ==>cindy ==>david ==>eliza ==>alice gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> select(all, 'v'). ......4> unfold(). ......5> values('name'). ......6> fold() ==>[alice,bobby,cindy,david,eliza,alice] For analysis consider temporarily promoting the anonymous traversal to the parent traversal as it might allow better focus on the actual result. In this case, the store() side- effects are not relevant to the specific analysis of the contents of the by() modulator. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Clarify Results 2A B C
  • 40. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold()). .....15> unfold(). .....16> sack(assign). .....17> by(constant(1d)). .....18> sack(div). .....19> by(union(constant(1d), .....20> tail(local, 1)).sum()). .....21> sack(mult). .....22> by(limit(local, 1)). .....23> sack().sum()). .....24> cap('a') ==>[alice,[alice,bobby,cindy,david,eliza,alice],[9,8,7,6,10],18.833333333333332]
  • 41. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold())). .....15> cap('a').next() ==>alice ==>[alice,bobby,cindy,david,eliza,alice] ==>[9,8,7,6,10] ==>[[9,0],[8,1],[7,2],[6,3],[10,4]] It may be necessary to isolate anonymous traversals if they are especially complex. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Isolate for Analysis 1
  • 42. © 2018. All Rights Reserved. Isolate for Analysis 1 Validate Assumptions 3 ● Use values() or valueMap() for vertex/edge results ● Visualize results ● Consider temporarily promoting an anonymous traversal to its parent if it yields better clarity into the result ● Use path() to inspect what has been traversed ● Inspect step labels with select() ● Inspect contents of side- effects steps with cap() Clarify Results 2 ● Large or complex anonymous traversals may require their own isolated analysis ● Isolation within an anonymous traversal can produce misleading intermediate results - including the end portion of a traversal may be helpful
  • 43. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold()). .....15> unfold()). .....16> cap('a').next() ==>alice ==>[alice,bobby,cindy,david,eliza,alice] ==>[9,8,7,6,10] ==>[9,0] Analyzing portions of a traversal can produce misleading intermediate results that might leave an incorrect impression as to the overall intention of the traversal when executed as a whole. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Isolate for Analysis 1
  • 44. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold()). .....15> unfold(). .....16> sack(assign). .....17> by(constant(1d))). .....18> cap('a').next() ==>alice ==>[alice,bobby,cindy,david,eliza,alice] ==>[9,8,7,6,10] ==>[9,0] Analyzing portions of a traversal can produce misleading intermediate results that might leave an incorrect impression as to the overall intention of the traversal when executed as a whole. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Isolate for Analysis 1
  • 45. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold()). .....15> unfold(). .....16> sack(assign). .....17> by(constant(1d)). .....18> sack().sum()). .....19> cap('a').next() ==>alice ==>[alice,bobby,cindy,david,eliza,alice] ==>[9,8,7,6,10] ==>5.0 Include context from the end of a portion of a traversal to help ensure the intent of the overall traversal is consistent. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Isolate for Analysis 1
  • 46. © 2018. All Rights Reserved. Isolate for Analysis 1 Validate Assumptions 3 ● Use values() or valueMap() for vertex/edge results ● Visualize results ● Consider temporarily promoting an anonymous traversal to its parent if it yields better clarity into the result ● fold() can be a good temporary replacement for other reducing steps like sum(), max(), min(), etc. as it provides visibility to the values of that computation ● Use path() to inspect what has been traversed ● Inspect step labels with select() ● Inspect contents of side- effects steps with cap() Clarify Results 2 ● Large or complex anonymous traversals may require their own isolated analysis ● Isolation within an anonymous traversal can produce misleading intermediate results - including the end portion of a traversal may be helpful
  • 47. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold()). .....15> unfold(). .....16> sack(assign). .....17> by(constant(1d)). .....18> sack().fold()). .....19> cap('a').next() ==>alice ==>[alice,bobby,cindy,david,eliza,alice] ==>[9,8,7,6,10] ==>[1.0,1.0,1.0,1.0,1.0] Do not allow the actual steps in the traversal to prevent visibility into the nature of the computations that Gremlin is performing. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Clarify Results 2
  • 48. © 2018. All Rights Reserved. Isolate for Analysis 1 Validate Assumptions 3 ● Use values() or valueMap() for vertex/edge results ● Visualize results ● Consider temporarily promoting an anonymous traversal to its parent if it yields better clarity into the result ● fold() can be a good temporary replacement for other reducing steps like sum(), max(), min(), etc. as it provides visibility to the values of that computation ● Isolate results of interest ● Use path() to inspect what has been traversed ● Inspect step labels with select() ● Inspect contents of side- effects steps with cap() Clarify Results 2 ● Large or complex anonymous traversals may require their own isolated analysis ● Isolation within an anonymous traversal can produce misleading intermediate results - including the end portion of a traversal may be helpful
  • 49. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold()). .....15> unfold(). .....16> sack(assign). .....17> by(constant(1d)). .....18> sack(div). .....19> by(union(constant(1d), .....20> tail(local, 1)).sum()). .....21> sack().fold()). .....22> cap('a').unfold().skip(3).fold().next() ==>[1.0,0.5,0.3333333333333333,0.25,0.2] Limit output as necessary to focus on the aspects of the results that are most under consideration. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Clarify Results 2
  • 50. © 2018. All Rights Reserved. Isolate for Analysis 1 Validate Assumptions 3 ● Use values() or valueMap() for vertex/edge results ● Visualize results ● Consider temporarily promoting an anonymous traversal to its parent if it yields better clarity into the result ● fold() can be a good temporary replacement for other reducing steps like sum(), max(), min(), etc. as it provides visibility to the values of that computation ● Isolate results of interest ● Use path() to inspect what has been traversed ● Inspect step labels with select() ● Inspect contents of side- effects steps with cap() Clarify Results 2 ● Large or complex anonymous traversals may require their own isolated analysis ● Isolation within an anonymous traversal can produce misleading intermediate results - including the end portion of a traversal may be helpful ● Simulate a traversal from a specific known input with the inject() start step
  • 51. © 2018. All Rights Reserved. gremlin> g.inject([9,0],[8,1],[7,2],[6,3],[10,4]). ......1> sack(assign). ......2> by(constant(1d)). ......3> sack(div). ......4> by(union(constant(1d),tail(local,1)).sum()). ......5> sack() ==>1.0 ==>0.5 ==>0.3333333333333333 ==>0.25 ==>0.2 gremlin> g.inject([10,4]). ......1> union(constant(1d),tail(local,1)) ==>1.0 ==>4 gremlin> g.inject([10,4]). ......1> union(constant(1d),tail(local,1)). ......2> sum() ==>5.0 gremlin> 1.0d / g.inject([10,4]). ......1> union(constant(1d),tail(local,1)). ......2> sum().next() ==>0.2 Lost? Reclaim focus by simulating just the portion of the traversal that is not yet understood. g.V().has('name','alice').as('v'). repeat(outE().as('e').inV().as('v')). until(has('name','alice')). store('a'). by('name'). store('a'). by(select(all, 'v').unfold().values('name').fold()). store('a'). by(select(all, 'e').unfold(). store('x'). by(union(values('value'), select('x').count(local)).fold()). cap('x'). store('a'). by(unfold().limit(local, 1).fold()). unfold(). sack(assign). by(constant(1d)). sack(div). by(union(constant(1d), tail(local, 1)).sum()). sack(mult). by(limit(local, 1)). sack().sum()). cap('a') Isolate for Analysis 1 B A C D
  • 52. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold()). .....15> unfold(). .....16> sack(assign). .....17> by(constant(1d)). .....18> sack(div). .....19> by(union(constant(1d), .....20> tail(local, 1)).sum()). .....21> sack(mult). .....22> by(limit(local, 1)). .....23> sack().sum()). .....24> cap('a') ==>[alice,[alice,bobby,cindy,david,eliza,alice],[9,8,7,6,10],18.833333333333332]
  • 53. © 2018. All Rights Reserved. gremlin> g.V().has('name','alice').as('v'). ......1> repeat(outE().as('e').inV().as('v')). ......2> until(has('name','alice')). ......3> store('a'). ......4> by('name'). ......5> store('a'). ......6> by(select(all, 'v').unfold().values('name').fold()). ......7> store('a'). ......8> by(select(all, 'e').unfold(). ......9> store('x'). .....10> by(union(values('value'), .....11> select('x').count(local)).fold()). .....12> cap('x'). .....13> store('a'). .....14> by(unfold().limit(local, 1).fold()). .....15> unfold(). .....16> sack(assign). .....17> by(constant(1d)). .....18> sack(div). .....19> by(union(constant(1d), .....20> tail(local, 1)).sum()). .....21> sack(mult). .....22> by(limit(local, 1)). .....23> sack().sum()). .....24> cap('a') ==>[alice,[alice,bobby,cindy,david,eliza,alice],[9,8,7,6,10],18.833333333333332] Overriding traversers with by()- modulators Creating indexed values Using sack() for computations Result construction with side-effects Methods of cycle-detection Traversal patterns identified as a result of Gremlin Debugging Cycle Step label access and collection manipulation
  • 54. © 2018. All Rights Reserved. Isolate for Analysis 1 Validate Assumptions 3 ● Use values() or valueMap() for vertex/edge results ● Visualize results ● Consider temporarily promoting an anonymous traversal to its parent if it yields better clarity into the result ● fold() can be a good temporary replacement for other reducing steps like sum(), max(), min(), etc. as it provides visibility to the values of that computation ● Isolate results of interest ● Use path() to inspect what has been traversed ● Inspect step labels with select() ● Inspect contents of side- effects steps with cap() Clarify Results 2 ● Large or complex anonymous traversals may require their own isolated analysis ● Isolation within an anonymous traversal can produce misleading intermediate results - including the end portion of a traversal may be helpful ● Simulate a traversal from a specific known input with the inject() start step
  • 55. © 2018. All Rights Reserved. What's next?
  • 56. © 2017. All Rights Reserved. ● Apache TinkerPop Website ○ http://tinkerpop.apache.org/ ● Gremlin Recipes ○ http://tinkerpop.apache.org/docs/current/recipes/ ● The Gremlin Compendium ○ http://www.doanduyhai.com/blog/?p=13460 ● Practical Gremlin ○ http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html ● Gremlin DSLs - Part I ○ https://www.datastax.com/dev/blog/gremlin-dsls-in-java-with-dse-graph ● Gremlin DSLs - Part II ○ https://academy.datastax.com/content/gremlin-dsls-python-dse-graph Resources