简体   繁体   中英

Gremlin continue traversal only if 2 vertices are not the same

I have a query which looks at 2 different vertices and I want to stop traversing if they don't both roll up to the same root ancestor via a path of "contains" edges.

 g.V('node1')
  .until(hasLabel('root')).repeat(in('contains')).as('node1Root')
  .V('node2')
  .until(hasLabel('root')).repeat(in('contains')).as('node2Root')
  //FILTER|WHERE clause

I'd like to confirm that node1Root and node2root are the same vertex before continuing the traversal, but for the life of me I cannot figure out how to do this.

I've tried the following:

 g.V('node1')
  .until(hasLabel('root')).repeat(in('contains')).as('node1Root')
  .V('node2')
  .until(hasLabel('root')).repeat(in('contains')).as('node2Root')
  //.where('node1Root', P.eq('node2Root')
  //.where(select("node1Root").is(P.eq("node2Root")))
  //.where(select("node1Root").is("node2Root"))

What's interesting is that the following query does work to filter appropriately.

g.V('node1').as('1')
 .V('node2').as('2')
 .where('1', P.eq('2'))

I'm not sure if there's something up with the until/repeat that screws it up or if I'm just doing something blatantly wrong. Any help would be much appreciated.

Thanks!

I found How to check equality with nodes from an earlier part of query in Gremlin?

and it seems like you use "as" with the same key as the previous "as" and if they match its considered equal.

So here's the winner (I think):

 g.V('node1')
.until(hasLabel('root')).repeat(in('contains')).as('node1Root')
.V('node2')
.until(hasLabel('root')).repeat(in('contains')).as('node2Root')
.where(select('node1Root').as('node2Root')
//.not(select('node1Root').as('node2Root')) //OR this to determine they aren't the same
//continue traversal

I also found that my original issue was that the.until().repeat() steps could return a LIST, but in my case I know that my graph model will always return a single 'root' so to make it work, I can use 'unfold'

 g.V('node1')
 .until(hasLabel('root')).repeat(in('contains')).unfold().as('node1Root')
 .V('node2')
 .until(hasLabel('root')).repeat(in('contains')).unfold().as('node2Root')
 .where('node1Root', P.eq('node2Root')

I think I'll be going with the second solution because I'm much more confident in it, unless I hear otherwise.

You can try this gremlin query

g.V(node1-id)
.map(until(hasLabel('root')).repeat(in().aggregate('x')).cap('x')).as("array")
 .V(node2-id)
  .until(
     
      as("i").select("array").unfold().as("j")
      .where("i", eq("j"))
      
      ).repeat(in())

Here we are putting all the vertices in path to root from node1 in an array, and secondly we are checking existence of node in array.

this query can only work with traversal with only one iteration because aggregate step collect to a global variable to traversal that means it will be same array for every iteration. To fix this If you are doing this on jvm do use lamda/groovy closures


g.V(node-start-id-1,node-start-id-2)
.map(
    { x->
    
    var v = x.get()
    var g =  getGraph().get().traversal();
    g.V(v.id())until(hasLabel('root')).repeat(in().aggregate('x')).cap('x')).next()
    }
)
.as("array")
 .V(node2-id)
  .until(

      as("i").select("array").unfold().as("j")
      .where("i", eq("j"))

      ).repeat(in())

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