SlideShare une entreprise Scribd logo
1  sur  56
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

Contenu connexe

Tendances

Substrait Overview.pdf
Substrait Overview.pdfSubstrait Overview.pdf
Substrait Overview.pdfRinat Abdullin
 
Introduction to Apache Flink - Fast and reliable big data processing
Introduction to Apache Flink - Fast and reliable big data processingIntroduction to Apache Flink - Fast and reliable big data processing
Introduction to Apache Flink - Fast and reliable big data processingTill Rohrmann
 
Programming in Spark using PySpark
Programming in Spark using PySpark      Programming in Spark using PySpark
Programming in Spark using PySpark Mostafa
 
Graphql presentation
Graphql presentationGraphql presentation
Graphql presentationVibhor Grover
 
Physical Plans in Spark SQL
Physical Plans in Spark SQLPhysical Plans in Spark SQL
Physical Plans in Spark SQLDatabricks
 
Introduction to memcached
Introduction to memcachedIntroduction to memcached
Introduction to memcachedJurriaan Persyn
 
Intro to Cypher
Intro to CypherIntro to Cypher
Intro to CypherNeo4j
 
Pyspark Tutorial | Introduction to Apache Spark with Python | PySpark Trainin...
Pyspark Tutorial | Introduction to Apache Spark with Python | PySpark Trainin...Pyspark Tutorial | Introduction to Apache Spark with Python | PySpark Trainin...
Pyspark Tutorial | Introduction to Apache Spark with Python | PySpark Trainin...Edureka!
 
Introduction to graphQL
Introduction to graphQLIntroduction to graphQL
Introduction to graphQLMuhilvarnan V
 
Streaming Data Lakes using Kafka Connect + Apache Hudi | Vinoth Chandar, Apac...
Streaming Data Lakes using Kafka Connect + Apache Hudi | Vinoth Chandar, Apac...Streaming Data Lakes using Kafka Connect + Apache Hudi | Vinoth Chandar, Apac...
Streaming Data Lakes using Kafka Connect + Apache Hudi | Vinoth Chandar, Apac...HostedbyConfluent
 
Introduction to GraphQL: Mobile Week SF
Introduction to GraphQL: Mobile Week SFIntroduction to GraphQL: Mobile Week SF
Introduction to GraphQL: Mobile Week SFAmazon Web Services
 
Building Applications with a Graph Database
Building Applications with a Graph DatabaseBuilding Applications with a Graph Database
Building Applications with a Graph DatabaseTobias Lindaaker
 
Apache Spark - Basics of RDD | Big Data Hadoop Spark Tutorial | CloudxLab
Apache Spark - Basics of RDD | Big Data Hadoop Spark Tutorial | CloudxLabApache Spark - Basics of RDD | Big Data Hadoop Spark Tutorial | CloudxLab
Apache Spark - Basics of RDD | Big Data Hadoop Spark Tutorial | CloudxLabCloudxLab
 
Using LLVM to accelerate processing of data in Apache Arrow
Using LLVM to accelerate processing of data in Apache ArrowUsing LLVM to accelerate processing of data in Apache Arrow
Using LLVM to accelerate processing of data in Apache ArrowDataWorks Summit
 
The Graph Database Universe: Neo4j Overview
The Graph Database Universe: Neo4j OverviewThe Graph Database Universe: Neo4j Overview
The Graph Database Universe: Neo4j OverviewNeo4j
 
Web-Scale Graph Analytics with Apache Spark with Tim Hunter
Web-Scale Graph Analytics with Apache Spark with Tim HunterWeb-Scale Graph Analytics with Apache Spark with Tim Hunter
Web-Scale Graph Analytics with Apache Spark with Tim HunterDatabricks
 
A Thorough Comparison of Delta Lake, Iceberg and Hudi
A Thorough Comparison of Delta Lake, Iceberg and HudiA Thorough Comparison of Delta Lake, Iceberg and Hudi
A Thorough Comparison of Delta Lake, Iceberg and HudiDatabricks
 
Native Support of Prometheus Monitoring in Apache Spark 3.0
Native Support of Prometheus Monitoring in Apache Spark 3.0Native Support of Prometheus Monitoring in Apache Spark 3.0
Native Support of Prometheus Monitoring in Apache Spark 3.0Databricks
 
Apache Flink and what it is used for
Apache Flink and what it is used forApache Flink and what it is used for
Apache Flink and what it is used forAljoscha Krettek
 

Tendances (20)

Substrait Overview.pdf
Substrait Overview.pdfSubstrait Overview.pdf
Substrait Overview.pdf
 
Introduction to Apache Flink - Fast and reliable big data processing
Introduction to Apache Flink - Fast and reliable big data processingIntroduction to Apache Flink - Fast and reliable big data processing
Introduction to Apache Flink - Fast and reliable big data processing
 
Programming in Spark using PySpark
Programming in Spark using PySpark      Programming in Spark using PySpark
Programming in Spark using PySpark
 
Graphql presentation
Graphql presentationGraphql presentation
Graphql presentation
 
Physical Plans in Spark SQL
Physical Plans in Spark SQLPhysical Plans in Spark SQL
Physical Plans in Spark SQL
 
Introduction to memcached
Introduction to memcachedIntroduction to memcached
Introduction to memcached
 
Intro to Cypher
Intro to CypherIntro to Cypher
Intro to Cypher
 
Pyspark Tutorial | Introduction to Apache Spark with Python | PySpark Trainin...
Pyspark Tutorial | Introduction to Apache Spark with Python | PySpark Trainin...Pyspark Tutorial | Introduction to Apache Spark with Python | PySpark Trainin...
Pyspark Tutorial | Introduction to Apache Spark with Python | PySpark Trainin...
 
Introduction to graphQL
Introduction to graphQLIntroduction to graphQL
Introduction to graphQL
 
Spark graphx
Spark graphxSpark graphx
Spark graphx
 
Streaming Data Lakes using Kafka Connect + Apache Hudi | Vinoth Chandar, Apac...
Streaming Data Lakes using Kafka Connect + Apache Hudi | Vinoth Chandar, Apac...Streaming Data Lakes using Kafka Connect + Apache Hudi | Vinoth Chandar, Apac...
Streaming Data Lakes using Kafka Connect + Apache Hudi | Vinoth Chandar, Apac...
 
Introduction to GraphQL: Mobile Week SF
Introduction to GraphQL: Mobile Week SFIntroduction to GraphQL: Mobile Week SF
Introduction to GraphQL: Mobile Week SF
 
Building Applications with a Graph Database
Building Applications with a Graph DatabaseBuilding Applications with a Graph Database
Building Applications with a Graph Database
 
Apache Spark - Basics of RDD | Big Data Hadoop Spark Tutorial | CloudxLab
Apache Spark - Basics of RDD | Big Data Hadoop Spark Tutorial | CloudxLabApache Spark - Basics of RDD | Big Data Hadoop Spark Tutorial | CloudxLab
Apache Spark - Basics of RDD | Big Data Hadoop Spark Tutorial | CloudxLab
 
Using LLVM to accelerate processing of data in Apache Arrow
Using LLVM to accelerate processing of data in Apache ArrowUsing LLVM to accelerate processing of data in Apache Arrow
Using LLVM to accelerate processing of data in Apache Arrow
 
The Graph Database Universe: Neo4j Overview
The Graph Database Universe: Neo4j OverviewThe Graph Database Universe: Neo4j Overview
The Graph Database Universe: Neo4j Overview
 
Web-Scale Graph Analytics with Apache Spark with Tim Hunter
Web-Scale Graph Analytics with Apache Spark with Tim HunterWeb-Scale Graph Analytics with Apache Spark with Tim Hunter
Web-Scale Graph Analytics with Apache Spark with Tim Hunter
 
A Thorough Comparison of Delta Lake, Iceberg and Hudi
A Thorough Comparison of Delta Lake, Iceberg and HudiA Thorough Comparison of Delta Lake, Iceberg and Hudi
A Thorough Comparison of Delta Lake, Iceberg and Hudi
 
Native Support of Prometheus Monitoring in Apache Spark 3.0
Native Support of Prometheus Monitoring in Apache Spark 3.0Native Support of Prometheus Monitoring in Apache Spark 3.0
Native Support of Prometheus Monitoring in Apache Spark 3.0
 
Apache Flink and what it is used for
Apache Flink and what it is used forApache Flink and what it is used for
Apache Flink and what it is used for
 

Similaire à Gremlin's Anatomy

A well-typed program never goes wrong
A well-typed program never goes wrongA well-typed program never goes wrong
A well-typed program never goes wrongJulien Wetterwald
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To ScalaPeter Maas
 
Python Workshop. LUG Maniapl
Python Workshop. LUG ManiaplPython Workshop. LUG Maniapl
Python Workshop. LUG ManiaplAnkur Shrivastava
 
Evolving The Java Language
Evolving The Java LanguageEvolving The Java Language
Evolving The Java LanguageQConLondon2008
 
Scala as a Declarative Language
Scala as a Declarative LanguageScala as a Declarative Language
Scala as a Declarative Languagevsssuresh
 
JavaScript and jQuery Fundamentals
JavaScript and jQuery FundamentalsJavaScript and jQuery Fundamentals
JavaScript and jQuery FundamentalsBG Java EE Course
 
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...
Developing Your Own Flux Packages by David McKay | Head of Developer Relation...InfluxData
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005Tugdual Grall
 
Functional programming-advantages
Functional programming-advantagesFunctional programming-advantages
Functional programming-advantagesSergei Winitzki
 
javasebeyondbasics
javasebeyondbasicsjavasebeyondbasics
javasebeyondbasicswebuploader
 
Matlab tips and tricks
Matlab tips and tricksMatlab tips and tricks
Matlab tips and tricksTariq kanher
 
Jscript Fundamentals
Jscript FundamentalsJscript Fundamentals
Jscript Fundamentalsrspaike
 
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...
Introduction To TensorFlow | Deep Learning Using TensorFlow | TensorFlow Tuto...Edureka!
 
SeaJUG March 2004 - Groovy
SeaJUG March 2004 - GroovySeaJUG March 2004 - Groovy
SeaJUG March 2004 - GroovyTed Leung
 
T02 a firstcprogram
T02 a firstcprogramT02 a firstcprogram
T02 a firstcprogramprincepavan
 

Similaire à Gremlin's Anatomy (20)

A well-typed program never goes wrong
A well-typed program never goes wrongA well-typed program never goes wrong
A well-typed program never goes wrong
 
Introduction To Scala
Introduction To ScalaIntroduction To Scala
Introduction To Scala
 
C tutorial
C tutorialC tutorial
C tutorial
 
Python Workshop. LUG Maniapl
Python Workshop. LUG ManiaplPython Workshop. LUG Maniapl
Python Workshop. LUG Maniapl
 
Matlab Basic Tutorial
Matlab Basic TutorialMatlab Basic Tutorial
Matlab Basic Tutorial
 
Evolving The Java Language
Evolving The Java LanguageEvolving The Java Language
Evolving The Java Language
 
Scala as a Declarative Language
Scala as a Declarative LanguageScala as a Declarative Language
Scala as a Declarative Language
 
JavaScript and jQuery Fundamentals
JavaScript and jQuery FundamentalsJavaScript and jQuery Fundamentals
JavaScript and jQuery Fundamentals
 
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...
Developing Your Own Flux Packages by David McKay | Head of Developer Relation...
 
Introduction To Groovy 2005
Introduction To Groovy 2005Introduction To Groovy 2005
Introduction To Groovy 2005
 
Functional programming-advantages
Functional programming-advantagesFunctional programming-advantages
Functional programming-advantages
 
C Programming
C ProgrammingC Programming
C Programming
 
C++ theory
C++ theoryC++ theory
C++ theory
 
javasebeyondbasics
javasebeyondbasicsjavasebeyondbasics
javasebeyondbasics
 
Dart workshop
Dart workshopDart workshop
Dart workshop
 
Matlab tips and tricks
Matlab tips and tricksMatlab tips and tricks
Matlab tips and tricks
 
Jscript Fundamentals
Jscript FundamentalsJscript Fundamentals
Jscript Fundamentals
 
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...
Introduction To TensorFlow | Deep Learning Using TensorFlow | TensorFlow Tuto...
 
SeaJUG March 2004 - Groovy
SeaJUG March 2004 - GroovySeaJUG March 2004 - Groovy
SeaJUG March 2004 - Groovy
 
T02 a firstcprogram
T02 a firstcprogramT02 a firstcprogram
T02 a firstcprogram
 

Dernier

Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 

Dernier (20)

Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 

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