Reputation: 241
Every vertex in my graph has at least a name property. I have a label L set S of name values. Now I want to collect the values of the name property of all vertices that can be reached (recursively) via a specific outgoing edge with edge label EL from the vertices with the names in set S.
My current solution for a single start node with name S1 looks like the following:
g.traversal().V().hasLabel(L)
.has("name", S1)
.repeat(__.optional(__.out(EL)))
.until(__.out(EL).count().is(0))
.path()
.forEachRemaining(path -> {
path.forEach(e -> System.out.println(((Vertex)e).property("name").value()));});
The println
is only to see that this produces the expected result, normally I would collect the names in a Set.
Is there a better way to collect the values of the name property of all the vertices reachable via outgoing edges with label EL?
And what would be the best way to start with multiple vertices (where only the name is known from Set S)?
Currently, the structure is a tree, but if there may by cycles, does the code above prevents endless loops? If not, how can this be done?
Upvotes: 4
Views: 2927
Reputation: 6792
Your approach is a good start.
To start from a set of multiple vertices, use the P.within()
predicate. TinkerPop provides several other predicates.
Use simplePath()
to prevent repeating through loops.
Use store()
to keep track of items as it traverses the graph. The by("name")
modulator will store the "name" property rather than the vertex.
To get out the result, use cap()
to output the items it stored during the traversal. The result at this point is a Set
which potentially contains duplicates. Use unfold()
to turn the Set
into an iterator that we can dedup()
then finish with toSet()
.
graph.traversal().V().hasLabel(L).has("name", P.within(S)).
repeat( __.out(EL).simplePath().store("x").by("name") ).
until( __.outE(EL).count().is(0) ).
cap("x").unfold().dedup().toSet()
Upvotes: 6