AT
Join ServerApache TinkerPop
questions
Question about `local` step
Sometimes I don't understand how local step works. I want to count how many elements in each array, this query looks correct but gives unexpected result. How to fix it?
g.inject([1,2],[1],[1,2]).local(unfold().count())
if you just want to count each, the most Gremlinesque way is to do:
gremlin> g.inject([1,2],[1],[1,2]).count(local)
==>2
==>2
==>1
local()
step has some nuances to it explored here: http://stephen.genoprime.com/snippet/2020/04/25/snippet-10.html and more recently here: https://discord.com/channels/838910279550238720/888507863847284766/1080592362297901088There appears to be a subtle difference between
There are 3 arrays but only 2 traversers. This creates the following results:
.count(local)
and .local(unfold().count())
. Based on my observations, .count(local)
performs a separate count on each incoming array. .local(unfold().count())
takes each incoming traverser, and runs is through an unfold().count()
. The subtle difference is regarding bulked traversers. A bulked traverser can contain 2 copies of the same object, but it still gets fed into a single execution of the unfold().count()
child traversal.g.inject([1,2],[1],[1,2])
appears to spawn 2 traversers:{t = [1], bulk=1}
, {t = [1,2], bulk=2}
.There are 3 arrays but only 2 traversers. This creates the following results:
gremlin> g.inject([1,2],[1],[1,2]).count(local)
==>2
==>2
==>1
gremlin> g.inject([1,2],[1],[1,2]).local(unfold().count())
==>4
==>1
It appears that even when disabling bulking,
I believe this may be a bug in the inject step. Thoughts @spmallette ?
inject()
still only spawns 2 traversers in this case.gremlin> g.inject([1,2],[1],[1,2]).local(unfold().count())
==>4
==>1
gremlin> g.withBulk(false).inject([1,2],[1],[1,2]).local(unfold().count())
==>2
==>1
I believe this may be a bug in the inject step. Thoughts @spmallette ?
I'm definitely turning that thing i wrote in the discord link above into a blog post today. if i didn't re-read that i'd have probably gone down into a hole of debugging with this example. sorry i didn't understand if this was the real question here.
anyway, no, not a bug. that's just how
The objects are all
local()
works. a global count()
(not count(local)
) occurs over the same objects in the stream. maybe this is easier to see:gremlin> g.inject([1],[1],[1]).local(unfold().count())
==>3
The objects are all
List
with a 1
in there so they all count under the same traverser object. kinda weird but there are some use cases where you want to do object-local traversal computations. this example with inject()
is fairly contrived so it looks especially strange. whenever i see local()
in a traversal, i always stop to ask if it really needs to be there. often, it should be replaced with a Scope.local
argument (like count(local)
in this case) or a direct replacement with map()
or flatMap()
.hope i didn't jump to "mark solution" too quickly....wanted that link in Answer Overflow so that i could complete the blog post: https://stephen.genoprime.com/snippet/2023/04/13/snippet-15.html