Technology•September 25, 2016
Gremlin’s Time Machine
$ bin/gremlin.sh
\,,,/
(o o)
-----oOOo-(3)-oOOo-----
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV('person'). // <1>
......1> property('startTime',1979).
......2> property('name','marko','startTime',1979)
==>v[0]
gremlin> g.addV('person'). // <2>
......1> property('startTime',1975).
......2> property('name','stephen','startTime',1975)
==>v[3]
gremlin> g.V().has('name','marko').as('a'). // <3>
......1> V().has('name','stephen').as('b').
......2> addE('knows').from('a').to('b').
......3> property('startTime',2010)
==>e[6][0-knows->3]
gremlin> g.addV('person'). // <1>
......1> property('startTime',1983).
......2> property('name','bob','startTime',1983)
==>v[7]
gremlin> g.V().has('name','marko').as('a'). // <2>
......1> V().has('name','bob').as('b').
......2> addE('knows').from('a').to('b').
......3> property('startTime',2012).
......4> property('endTime',2015)
==>e[10][0-knows->7]
gremlin> g.V().has('name','marko').out('knows').values('name')
==>stephen
==>bob
gremlin> g.V().has('name','marko').outE('knows').
......1> has('startTime',lte(2016)).
......2> and(hasNot('endTime').
......3> or().
......4> has('endTime',gt(2016))).
......5> inV().values('name')
==>stephen
gremlin> strategy = SubgraphStrategy.build(). // <1>
......1> edges(has('startTime',lte(2016)).
......2> or(hasNot('endTime'),
......3> has('endTime',gt(2016)))).create()
==>SubgraphStrategy
gremlin> g.withStrategies(strategy).V().has('name','marko').out('knows').values('name') // <2>
==>stephen
timeWindow = { startTime, endTime -> // <1>
assert startTime <= endTime
SubgraphStrategy.build().
edges(has('startTime',lte(startTime)).
or(hasNot('endTime'),has('endTime',gt(endTime)))).create()
}
timePoint = { timePoint -> timeWindow(timePoint,timePoint) } // <2>
currentPoint = { timePoint(Calendar.getInstance().get(Calendar.YEAR)) } // <3>
gremlin> g.withStrategies(timeWindow(2012,2014)).V().has('name','marko').out('knows').values('name') // <1>
==>stephen
==>bob
gremlin> g.withStrategies(timePoint(2015)).V().has('name','marko').out('knows').values('name') // <2>
==>stephen
gremlin> g.withStrategies(currentPoint()).V().has('name','marko').out('knows').values('name') // <3>
==>stephen
gremlin> g = g.withStrategies(currentPoint()) // <1>
==>graphtraversalsource[tinkergraph[vertices:3 edges:2], standard]
gremlin> g.V().has('name','marko').both('knows').values('name') // <2>
==>stephen
gremlin> g.V().has('name','stephen').both('knows').values('name') // <3>
==>marko
gremlin> g.V().has('name','bob').both('knows').values('name') // <4>
gremlin>
timeWindow = { startTime, endTime, elementClasses ->
assert startTime <= endTime
timeTraversal = has('startTime',lte(startTime)).
or(hasNot('endTime'),has('endTime',gt(endTime)))
builder = SubgraphStrategy.build()
if(Vertex.class in elementClasses)
builder = builder.vertices(timeTraversal.clone())
if(Edge.class in elementClasses)
builder = builder.edges(timeTraversal.clone())
if(VertexProperty.class in elementClasses)
builder = builder.vertexProperties(timeTraversal.clone())
return builder.create()
}
timePoint = { timePoint, elementClasses -> timeWindow(timePoint, timePoint, elementClasses) }
currentPoint = { elementClasses -> timePoint(Calendar.getInstance().get(Calendar.YEAR), elementClasses) }
gremlin> g = g.withoutStrategies(SubgraphStrategy) // <1>
==>graphtraversalsource[tinkergraph[vertices:3 edges:2], standard]
gremlin> g.V().has('name','bob').property('endTime',2015) // <2>
==>v[7]
gremlin> g.V().has('name','stephen').as('a'). // <3>
......1> V().has('name','bob').as('b').
......2> addE('knows').from('a').to('b').property('startTime',2012)
==>e[12][3-knows->7]
gremlin> g.withStrategies(currentPoint([Edge])).V().has('name','stephen').both('knows').values('name') // <1>
==>bob
==>marko
gremlin> g.withStrategies(currentPoint([Vertex,Edge])).V().has('name','stephen').both('knows').values('name') // <2>
==>marko
gremlin> g.V().has('name','marko').
......1> property(list,'spirit','happy','startTime',1979,'endTime',2013). // <1>
......2> property(list,'spirit','sad','startTime',2013,'endTime',2014).
......3> property(list,'spirit','happy','startTime',2014)
==>v[0]
gremlin>
gremlin> g.V().has('name','stephen'). // <2>
......1> property(list,'spirit','happy','startTime',1975)
==>v[3]
gremlin>
gremlin> g.V().has('name','bob'). // <3>
......1> property(list,'spirit','happy','startTime',1983,'endTime',2014).
......2> property(list,'spirit','sad','startTime',2014)
==>v[7]
gremlin> g.withStrategies(timePoint(2012,[Vertex,Edge,VertexProperty])).V().valueMap('name','spirit') // <1>
==>[name:[marko],spirit:[happy]]
==>[name:[stephen],spirit:[happy]]
==>[name:[bob],spirit:[happy]]
gremlin> g.withStrategies(timePoint(2014,[Vertex,Edge,VertexProperty])).V().valueMap('name','spirit') // <2>
==>[name:[marko],spirit:[happy]]
==>[name:[stephen],spirit:[happy]]
==>[name:[bob],spirit:[sad]]
gremlin> g.withStrategies(timePoint(2015,[Vertex,Edge,VertexProperty])).V().valueMap('name','spirit') // <3>
==>[name:[marko],spirit:[happy]]
==>[name:[stephen],spirit:[happy]]
gremlin> g.withStrategies(currentPoint([Vertex,Edge,VertexProperty])).V().valueMap('name','spirit') // <4>
==>[name:[marko],spirit:[happy]]
==>[name:[stephen],spirit:[happy]]
gremlin> g.withStrategies(timeWindow(2012,2014,[Vertex])).V().explain()
==>Traversal Explanation
====================================================================================================================================================================================
Original Traversal [GraphStep(vertex,[])]
SubgraphStrategy [D] [GraphStep(vertex,[]), HasStep([startTime.lte(2012)]), OrStep([[NotStep(![PropertiesStep([endTime],value)])], [HasStep([endTime.gt(2014)])]])]
...
TinkerGraphStepStrategy [P] [TinkerGraphStep(vertex,[startTime.lte(2012)]), OrStep([[NotStep(![PropertiesStep([endTime],property)])], [HasStep([endTime.gt(2014)])]])]
...
Final Traversal [TinkerGraphStep(vertex,[startTime.lte(2012)]), OrStep([[NotStep(![PropertiesStep([endTime],property)])], [HasStep([endTime.gt(2014)])]])]
// BEFORE SubgraphStrategy
[GraphStep(vertex,[])]
// AFTER SubgraphStrategy
[GraphStep(vertex,[]),
HasStep([startTime.lte(2012)]),
OrStep(
[[NotStep(![PropertiesStep([endTime],value)])],
[HasStep([endTime.gt(2014)])]])]
gremlin> g.withStrategies(timeWindow(2012,2014,[Edge])).V().out('knows').explain()
==>Traversal Explanation
============================================================================================================================================================================================================================================
Original Traversal [GraphStep(vertex,[]), VertexStep(OUT,[knows],vertex)]
SubgraphStrategy [D] [GraphStep(vertex,[]), VertexStep(OUT,[knows],edge), HasStep([startTime.lte(2012)]), OrStep([[NotStep(![PropertiesStep([endTime],value)])], [HasStep([endTime.gt(2014)])]]), EdgeVertexStep(IN)]
...
gremlin> g.withStrategies(timeWindow(2012,2014,[VertexProperty])).V().values('spirit').explain()
==>Traversal Explanation
================================================================================================================================================================================================================================================
Original Traversal [GraphStep(vertex,[]), PropertiesStep([spirit],value)]
SubgraphStrategy [D] [GraphStep(vertex,[]), PropertiesStep([spirit],property), HasStep([startTime.lte(2012)]), OrStep([[NotStep(![PropertiesStep([endTime],value)])], [HasStep([endTime.gt(2014)])]]), PropertyValueStep]
...
gremlin> system.graph("gremlins-time-machine").create() // <1>
gremlin> :remote config alias g gremlins-time-machine.g // <2>
==>g=gremlins-time-machine.g
// property definitions
schema.propertyKey('startTime').Int().create()
schema.propertyKey('endTime').Int().create()
schema.propertyKey('name').Text().properties('startTime','endTime').create() // <1>
schema.propertyKey('spirit').Text().multiple().properties('startTime','endTime').create() // <2>
// vertex and edge definitions
schema.vertexLabel('person').properties('startTime','endTime','name','spirit').create() // <3>
schema.edgeLabel('knows').properties('startTime','endTime').connection('person','person').create() // <4>
// graph- and vertex-centric index definitions
schema.vertexLabel('person').index('personByName').materialized().by('name').add() // <5>
schema.vertexLabel('person').index('spiritByStartTime').property('spirit').by('startTime').add() // <6>
schema.vertexLabel('person').index('knowsByStartTime').outE('knows').by('startTime').add() // <7>
g.addV('person'). // <1>
property('startTime',1979).
property('name','marko','startTime',1979).
property(list,'spirit','happy','startTime',1979,'endTime',2013).
property(list,'spirit','sad','startTime',2013,'endTime',2014).
property(list,'spirit','happy','startTime',2014)
g.addV('person'). // <2>
property('startTime',1975).
property('name','stephen','startTime',1975).
property(list,'spirit','happy','startTime',1975)
g.addV('person'). // <3>
property('startTime',1983).
property('endTime',2015).
property('name','bob','startTime',1983).
property(list,'spirit','happy','startTime',1983,'endTime',2014).
property(list,'spirit','sad','startTime',2014)
g.V().has('person','name','marko').as('a'). // <4>
V().has('person','name','stephen').as('b').
addE('knows').from('a').to('b').
property('startTime',2010)
g.V().has('person','name','marko').as('a'). // <5>
V().has('person','name','bob').as('b').
addE('knows').from('a').to('b').
property('startTime',2012).
property('endTime',2015)
g.V().has('person','name','stephen').as('a'). // <6>
V().has('person','name','bob').as('b').
addE('knows').from('a').to('b').
property('startTime',2012)
gremlin> g.withStrategies(currentPoint([Vertex])).V().has('person','name','marko').explain()
==>Traversal Explanation
======================================================================================================================================================================================================================================================
Original Traversal [GraphStep(vertex,[]), HasStep([~label.eq(person)]), HasStep([name.eq(marko)])]
SubgraphStrategy [D] [GraphStep(vertex,[]), HasStep([startTime.lte(2016)]), OrStep([[NotStep(![PropertiesStep([endTime],value)])], [HasStep([endTime.gt(2016)])]]), HasStep([~label.eq(person)]), HasStep([name.eq(marko)])]
...
GraphStepStrategy [P] [DsegGraphStep(vertex,[~label.=(person), name.=(marko), startTime.<=(2016)]), OrStep([[NotStep(![DsegPropertiesStep([endTime],property)])], [HasStep([endTime.>(2016)])]])]
...
gremlin> g.withStrategies(currentPoint([Edge])).V().outE('knows').explain()
==>Traversal Explanation
===========================================================================================================================================================================================================================
Original Traversal [GraphStep(vertex,[]), VertexStep(OUT,[knows],edge)]
SubgraphStrategy [D] [GraphStep(vertex,[]), VertexStep(OUT,[knows],edge), HasStep([startTime.lte(2016)]), OrStep([[NotStep(![PropertiesStep([endTime],value)])], [HasStep([endTime.gt(2016)])]])]
...
LocalEdgeQueryOptimizerStrategy [P] [GraphStep(vertex,[]), DsegVertexStep(OUT,[knows],[startTime.<=(2016)],edge), OrStep([[NotStep(![DsegPropertiesStep([endTime],property)])], [HasStep([endTime.>(2016)])]])]
...
gremlin> g.withStrategies(currentPoint([VertexProperty])).V().properties('spirit').explain()
==>Traversal Explanation
================================================================================================================================================================================================================================
Original Traversal [GraphStep(vertex,[]), PropertiesStep([spirit],property)]
SubgraphStrategy [D] [GraphStep(vertex,[]), PropertiesStep([spirit],property), HasStep([startTime.lte(2016)]), OrStep([[NotStep(![PropertiesStep([endTime],value)])], [HasStep([endTime.gt(2016)])]])]
...
LocalEdgeQueryOptimizerStrategy [P] [GraphStep(vertex,[]), DsegPropertiesStep([spirit],[startTime.<=(2016)],property), OrStep([[NotStep(![DsegPropertiesStep([endTime],property)])], [HasStep([endTime.>(2016)])]])]
...
gremlin> g.V().properties('spirit').has('startTime',lte(2016)).has('endTime',gt(2016)).explain()
==>Traversal Explanation
==================================================================================================================================================================
Original Traversal [GraphStep(vertex,[]), PropertiesStep([spirit],property), HasStep([startTime.lte(2016)]), HasStep([endTime.gt(2016)])]
...
LocalEdgeQueryOptimizerStrategy [P] [GraphStep(vertex,[]), DsegPropertiesStep([spirit],[startTime.<=(2016), endTime.>(2016)],property)]
...