Hi Everyone,

I'd like to discuss a breaking change to the behavior of limit()​ and range()​ 
steps inside repeat()​ that I am planning to create a pull request for soon 
against the 3.8-dev branch.

Currently, limit()​ and range()​ steps inside repeat()​ maintain global 
counters that persist across repeat iterations, leading to strange behavior. To 
demonstrate, consider the following limit()​ traversals for the Grateful Dead 
toy graph which are querying for pairs of song sequences starting with the song 
'JAM'.

This repeat()​ traversal does not produce results because the limit(2)​ counter 
reaches the global limit after the first iteration (note that 
RepeatUnrollStrategy​ is disabled so that the repeat()​ step is not stripped by 
strategy optimization):

gremlin> 
g.withoutStrategies(RepeatUnrollStrategy).V().has('name','JAM').repeat(out('followedBy').limit(2)).times(2).values('name’)​
gremlin>​

However, the following unrolled traversal without repeat()​ produces 2 results:

gremlin> 
g.V().has('name','JAM').out('followedBy').limit(2).out('followedBy').limit(2).propertyMap('name’)​
==>[name:[vp[name->HURTS ME TOO]]]​
==>[name:[vp[name->BLACK THROATED WIND]]]​

These examples demonstrate how having globally tracked limit()​ and range()​ 
counters inside repeat()​ are counter intuitive and instead should be tracked 
per-iteration.

My change will introduce per-iteration counter tracking, making the repeat()​ 
behaviour more consistent with unrolled traversals. For example, the following 
Grateful Dead repeat ()​ traversal will produce 2 results after the change:

gremlin> 
g.withoutStrategies(RepeatUnrollStrategy).V().has('name','JAM').repeat(out('followedBy').limit(2)).times(2).values('name’)​
==>[name:[vp[name->HURTS ME TOO]]]​
==>[name:[vp[name->BLACK THROATED WIND]]]​

Please let me know if you have any concerns or feedback regarding this change.

Cheers,

Andrea

Reply via email to