I have a graph that looks like this:
Using gremlin-scala, I'm trying to traverse from A and collect these tuples:
(A, Some(A1)), (B, None), (C, Some(A2))
So essentially I want to repeatedly take α
out edges and optionally branch to β
, collecting those outs. I am guessing I need to inject an empty "step" if there's no β
edge but I haven't been able to figure out how to do that.
I'm also a bit confused about how to rewind after traversing β
now that jump
has been mysteriously removed (TP 3.1+)
So far I have something like:
graph.V("A").untilWithTraverser(t => t.get.outE(α).notExists()
).repeat(_.out(α).as(foo).out(β).as(bar)).select((foo,bar)).toList
But this doesn't rewind back to the main traversal and fails if any nodes on the "trunk" are missing a β
out edge
This is my gremlin-scala solution, based on Daniel's answer.
val unionTraversal = __[(String, Vertex)].union(
__[Vertex].identity.map("blob" -> _),
__.out(Beta).map("beta" -> _)
).traversal
def pathTuplesToScalaTuples(path: Path) =
path.objects.asScala.map(_.asInstanceOf[java.util.ArrayList[(String, Vertex)]].asScala.toList).toList
val pathO = graph.V("A")
.until(_.not(_.out(Alpha)))
.repeat(_.out(Alpha))
.path.by(unionTraversal.fold).headOption
val tuples = pathO.map(pathTuplesToScalaTuples)
This, unfortunately, involves a couple of kludges to actually make the emitted vertices useful.
First, step labels get erased when passing an anonymous traversal into a union so you can't label your emitted sets with .as("blob")
-- this is what the workaround with wrapping them in tuples with string labels is for.
Second, gremlin-scala doesn't yet have a wrapper for Path
(and may never get it, because paths can have arbitrary structure) so we have to do an ugly ugly cast.