I'm working with IBM graph and using gremlin to try to filter certain vertices. My edges have two labels required and optional. this the situation:
V3 -- V5 -- V6
/ \
V1 \
\ \
V2 -- V4
This is a little like a supply/demand chain. V1 is an object that supplies two types of supplies (V3 and V2). V4 needs both supplies to be able to work. V5 needs both V3 and V6 to be able to work. Since I only have V2 and V3. I need a query that allows me to move from V2 and V3 to each outgoing vertex but exclude a vertex based on whether or not that vertex has an edge that is required (but allows for optional edges).
After much trying this is what a colleague came up with:
def g = graph.traversal(); g.V(1).out().outE().aggregate('edges').inV().where(inE('required').where(not(within('edges'))).count().is(eq(0))).dedup()
Is this the best way to do this? Or is there are smarter way?
Assuming this is your graph:
gremlin> g.addV().property(id,1).as('1').
......1> addV().property(id,2).as('2').
......2> addV().property(id,3).as('3').
......3> addV().property(id,4).as('4').
......4> addV().property(id,5).as('5').
......5> addV().property(id,6).as('6').
......6> addE('supplies').from('1').to('2').
......7> addE('supplies').from('1').to('3').
......8> addE('required').from('2').to('4').
......9> addE('required').from('3').to('4').
.....10> addE('required').from('3').to('5').
.....11> addE('required').from('6').to('5').iterate()
and this is the expected output:
gremlin> g.V(1).
......1> out().
......2> outE().
......3> aggregate('edges').
......4> inV().
......5> where(inE('required').
......6> where(not(within('edges'))).
......7> count().is(eq(0))).
......8> dedup()
==>v[4]
Then aggregating edges already traversed edges is probably the best approach. (It's always best to include a sample graph as a Gremlin script in your questions.) I suppose it is worth noting that you don't need the eq()
in your is()
and not(without(...))
is just without
:
gremlin> g.V(1).
......1> out().
......2> outE().
......3> aggregate('edges').
......4> inV().
......5> where(inE('required').
......6> where(without('edges')).
......7> count().is(0)).
......8> dedup()
==>v[4]
Or just do away with counting all together since you want those vertices that return no new edges to traverse:
gremlin> g.V(1).
......1> out().
......2> outE().
......3> aggregate('edges').
......4> inV().
......5> not(inE('required').
......6> where(without('edges'))).
......7> dedup()
==>v[4]
The above approach might be better as the immediate return of just one edge from
your filter of inE('required').where(not(within('edges')))
will immediately filter the vertex out and you don't have to wait for a count of all edges.