I have two gremlin queries, both with individual start steps. I have no control over their inner structure (they are passed to me as method arguments). My task is to combine them into a single traversal. So basically I need to implement this:
public GraphTraversal<*,*> createUnion(
GraphTraversal<*, *> t1,
GraphTraversal<*,*> t2
){
// how?
}
We have to assume that:
t1
and t2
have individual start steps (.V()
/ .E()
)t1
starts with .V()
, t2
may start with E()
or vice versa.I tried the gremlin union
step (which does accept sub-traversals), but the following (while syntactically valid) doesn't work:
t1.union(
__.identity(),
t2
)
... because union
steps in gremlin will always be evaluated per input element of t1. Clearly that's not what we want here.
I also tried the inject(...)
step:
t1.inject(t2.toList().toArray(new Object[0]))
There are two issues with this:
t2
is eagerly evaluated during the construction of the queryt2
will not be available in the resulting traversal.Are there any better ways to do this? Ideally a way that preserves the labels in t1
and t2
and preserves lazy evaluation?
We've often seen cases for union()
to be a start step, but it hasn't been implemented as such yet. You can workaround this by using inject()
and a throwaway traverser:
gremlin> t1 = __.V().has('person','name','josh');[]
gremlin> t2 = __.V().has('person','name','peter');[]
gremlin> g.inject(0).union(t1, t2)
==>v[4]
==>v[6]
The dummy or "0" is just used to start the traversal and then is ignored at the union()
since the child traversals start with mid-traversal V()
.
Take care to make sure that your traversal that uses this pattern will actually optimize the execution. An explain()
/profile()
should hint you into the underlying behavior.