TechnologySeptember 25, 2016

Gremlin’s Time Machine

Marko A. Rodriguez
Marko A. Rodriguez
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)]
...
Discover more
Gremlin
Share

One-stop Data API for Production GenAI

Astra DB gives JavaScript developers a complete data API and out-of-the-box integrations that make it easier to build production RAG apps with high relevancy and low latency.