简体   繁体   中英

Filtering for vertices on gremlin

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 -

gV().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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM