gremlin hasId should be equivalent to id().is(xxx) in apache-tinkerpop-gremlin-console-3.3.4-bin.zip

Viewed 1215

From my understanding of hasId step, it should be the same behavior to id().is() step. Which means the follow script should print the same result.

g.V().hasId(4)
g.V().id().is(4)

But unfortunately, the hasId() step seems not work as I expected, is there any something wrong from my side ? the whole script in below FYI.

gremlin> g.addV('Orange').property('price', '1.79').property('location', 'location-0').property('_classname', 'com.microsoft.spring.data.gremlin.common.domain.Orange')
==>v[4]
gremlin> g.V().id().is(0)
==>0
gremlin> g.V().id()
==>0
==>4
gremlin> g.addV('Orange').property('price', '1.79').property('location', 'location-0').property('_classname', 'com.microsoft.spring.data.gremlin.common.domain.Orange')
==>v[8]
gremlin> g.V().id()
==>0
==>4
==>8
gremlin> g.V().hasId(8)
gremlin> g.V().id().is(8)
==>8
1 Answers

You're running into an inconsistency in your graph's handling of ids and I assume that the graph you are using is TinkerGraph. It's default configuration for id lookups is to compare via equals() so, using your example, you can see what's going on:

gremlin> g.V().hasId(0)
gremlin> g.V().hasId(0L)
==>v[0]

So why does this work then:

gremlin> g.V().id().is(0)
==>0

For that answer, we compare the profile() of each traversal:

gremlin> g.V().hasId(0L).profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
TinkerGraphStep(vertex,[0])                                            1           1           0.755   100.00
                                            >TOTAL                     -           -           0.755        -
gremlin> g.V().id().is(0).profile()
==>Traversal Metrics
Step                                                               Count  Traversers       Time (ms)    % Dur
=============================================================================================================
TinkerGraphStep(vertex,[])                                             2           2           0.063    29.62
IdStep                                                                 2           2           0.089    41.73
IsStep(eq(0))                                                          1           1           0.061    28.65
                                            >TOTAL                     -           -           0.214        -

They compile to two different traversals. The first shows that the hasId() is optimized to a single TinkerGraphStep with the id applied to it which means it uses an index lookup (and thus equals()). On the other hand, when you use is() in the fashion that you are, the TinkerGraph query optimizer doesn't make note of that and simply uses a linear scan of ids and a in-memory filter with IsStep. IsStep is smarter about numbers comparisons than TinkerGraphStep is and it just knows that a "0" is a "0" and ignores the type.

You can get the same behavior from TinkerGraph though if you reconfigure its IdManager as discussed in Practical Gremlin and the Reference Documentation:

gremlin> conf = new BaseConfiguration()
==>org.apache.commons.configuration.BaseConfiguration@2c413ffc
gremlin> conf.setProperty("gremlin.tinkergraph.vertexIdManager","LONG")
gremlin> conf.setProperty("gremlin.tinkergraph.edgeIdManager","LONG")
gremlin> conf.setProperty("gremlin.tinkergraph.vertexPropertyIdManager","LONG");[]
gremlin> graph = TinkerGraph.open(conf)
==>tinkergraph[vertices:0 edges:0]
gremlin> g = graph.traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV('Orange').property('price', '1.79').property('location', 'location-0').property('_classname', 'com.microsoft.spring.data.gremlin.common.domain.Orange')
==>v[0]
gremlin> g.V(0)
==>v[0]
gremlin> g.V().hasId(0)
==>v[0]
gremlin> g.V().id().is(0)
==>0
Related