简体   繁体   中英

How to write Gremlin query to find parent vertices which have a specified edge?

I am a newbie to gremlin queries. I have a graph like below, and my source vertex is P3, I want to write a query that will get all the parent\\ancestor vertices (an vertex is parent\\ancetor of P3 if there is an path from that vertex to P3 with edges of type 'contains') of type 'Part' and have an Owner associated to them. So in this case the query should return P1 and P2 but not P.

Query to create sample data:

    g.addV(id, 'P1').property('label','part').as('p1')
.addV(id, 'P2').property('label','part').as('p2')
.addV(id, 'P3').property('label','part').as('p3')
.addV(id, 'P4').property('label','part').as('p4')
.addV(id, 'owner1').property('label','owner').as('o1')
.addV(id, 'owner2').property('label','owner').as('o2')
.addE('contains').from('p1').to('p2')
.addE('contains').from('p2').to('p3')
.addE('contains').from('p4').to('p3')
.addE('owns').from('o1').to('p1')
.addE('owns').from('o2').to('p2')

在此处输入图片说明

This is the query that I came up with, but the traversal stops once it finds a part vertex that has an owner vertex associated to it. How to update it to return both P1 and P2.

g.V('P3')
           .union(
                            inE().hasLabel('owns').inV(),
                repeat(inE().hasLabel('contains')
                                            .outV().hasLabel('part'))
                                            .until(inE().hasLabel('owns'))
                ).dedup()

I also tried using a sideEffect step to collect part vertices but didn't get required result.

g.V('P3').union(
inE().hasLabel('owns').inV(),
repeat(inE().sideEffect(hasLabel('owns').outV().as('parts'))
        .hasLabel('contains')
        .outV().hasLabel('part'))
)
.select('parts').dedup()

I revised your sample data code a bit as the syntax was wrong:

gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV('part').property(id, 'P1').as('p1').
......1>   addV('part').property(id, 'P2').as('p2').
......2>   addV('part').property(id, 'P3').as('p3').
......3>   addV('part').property(id, 'P4').as('p4').
......4>   addV('owner').property(id, 'owner1').as('o1').
......5>   addV('owner').property(id, 'owner2').as('o2').
......6>   addE('contains').from('p1').to('p2').
......7>   addE('contains').from('p2').to('p3').
......8>   addE('contains').from('p4').to('p3').
......9>   addE('owns').from('o1').to('p1').
.....10>   addE('owns').from('o2').to('p2').iterate()

I think you can simplify your traversal to just be a simple repeat() :

gremlin> g.V('P3').emit(inE('owns')).repeat(__.in('contains'))
==>v[P2]
==>v[P1]

Note the placement of the emit() step which controls the vertices that are output from the loop.

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