I have a combined path of both vertices and edges, and I'm trying to filter it for vertices only. I currently have the following -
g.V().outE().inV().outE().inV().path().unfold().filter(...)
How can one go from this to a collection without edges?
For a second I'll assume that your example is your actual query, in which case you can do it really easily by just getting rid of the edge traversals as follows:
g.V().out().out().path().unfold()
If your example is just a simplified version of your real traversal then the answer is a big more complicated. Here are a few options given the "modern" toy graph:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().outE().inV().outE().inV().path()
==>[v[1],e[8][1-knows->4],v[4],e[10][4-created->5],v[5]]
==>[v[1],e[8][1-knows->4],v[4],e[11][4-created->3],v[3]]
So, here's the output from my initial suggestion so we can compare to the other options which will use outE().inV()
:
gremlin> g.V().out().out().path().unfold()
==>v[1]
==>v[4]
==>v[5]
==>v[1]
==>v[4]
==>v[3]
I suppose you could label your steps and then select()
them all out:
gremlin> g.V().as('a').outE().inV().as('a').outE().inV().as('a').select(all,'a').unfold()
==>v[1]
==>v[4]
==>v[5]
==>v[1]
==>v[4]
==>v[3]
I like to generally avoid step labels if possible though so one way to filter out mixed graph elements is to choose a filter that can uniquely identify them. For example, in the modern graph I know that the the list of vertex and edge labels is globally unique (there is no vertex label that is the same as an edge label) so I can just do:
gremlin> g.V().outE().inV().outE().inV().path().unfold().hasLabel('person','software')
==>v[1]
==>v[4]
==>v[5]
==>v[1]
==>v[4]
==>v[3]
You can do similar tricks with has()
if you have some uniquely named property key or value. If you have none of those things then you might be stuck using a lambda which isn't so good:
gremlin> g.V().outE().inV().outE().inV().path().unfold().filter{it.get() instanceof Vertex}
==>v[1]
==>v[4]
==>v[5]
==>v[1]
==>v[4]
==>v[3]
Consider this example:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().repeat(outE().inV()).times(2).emit().path()
==>[v[1],e[9][1-created->3],v[3]]
==>[v[1],e[7][1-knows->2],v[2]]
==>[v[1],e[8][1-knows->4],v[4]]
==>[v[1],e[8][1-knows->4],v[4],e[10][4-created->5],v[5]]
==>[v[1],e[8][1-knows->4],v[4],e[11][4-created->3],v[3]]
==>[v[4],e[10][4-created->5],v[5]]
==>[v[4],e[11][4-created->3],v[3]]
==>[v[6],e[12][6-created->3],v[3]]
You know that every other path element is a vertex (and every other one is an edge). This allows you to use the "by" modifier to give each one a "type" (remember "by" steps are processed over the input in a round robin fashion):
gremlin> g.V().repeat(outE().inV()).times(2).emit().path().
......1> by(
......2> project('item', 'type').
......3> by(identity()).
......4> by(constant('vertex'))).
......5> by(
......6> project('item', 'type').
......7> by(identity()).
......8> by(constant('edge')))
==>[[item:v[1],type:vertex],[item:e[9][1-created->3],type:edge],[item:v[3],type:vertex]]
==>[[item:v[1],type:vertex],[item:e[7][1-knows->2],type:edge],[item:v[2],type:vertex]]
==>[[item:v[1],type:vertex],[item:e[8][1-knows->4],type:edge],[item:v[4],type:vertex]]
==>[[item:v[1],type:vertex],[item:e[8][1-knows->4],type:edge],[item:v[4],type:vertex],[item:e[10][4-created->5],type:edge],[item:v[5],type:vertex]]
==>[[item:v[1],type:vertex],[item:e[8][1-knows->4],type:edge],[item:v[4],type:vertex],[item:e[11][4-created->3],type:edge],[item:v[3],type:vertex]]
==>[[item:v[4],type:vertex],[item:e[10][4-created->5],type:edge],[item:v[5],type:vertex]]
==>[[item:v[4],type:vertex],[item:e[11][4-created->3],type:edge],[item:v[3],type:vertex]]
==>[[item:v[6],type:vertex],[item:e[12][6-created->3],type:edge],[item:v[3],type:vertex]]
See how each path element contains the type now? Getting what you want is now a little easier.
gremlin> g.V().repeat(outE().inV()).times(2).emit().path().
......1> by(
......2> project('item', 'type').
......3> by(identity()).
......4> by(constant('vertex'))).
......5> by(
......6> project('item', 'type').
......7> by(identity()).
......8> by(constant('edge'))).
......9> unfold().
.....10> where(select('type').is('vertex')).
.....11> select('item').
.....12> dedup()
==>v[1]
==>v[3]
==>v[2]
==>v[4]
==>v[5]
==>v[6]