Search code examples
gremlin

Gremlin arithmetic on where predicate?


In this question Gremlin graph traversal that uses previous edge property value to filter later edges we can use where to compare property of edge. I don't want just using simple neq or eq or gt. Can gremlin support on arithmetic on this two edge? suck like gtv('firstEdge', 0.2) or g.V(1).outE().has('weight',1.0).as('firstEdge').inV().outE().as('secondEdge').filter((secondEdge-firstEdge) > 0.2)

I seem don't find such thing in document.


Solution

  • There are a couple of ways to approach a situation like this. For simple queries where you just want a+b < some value, using sack works well. For example, using the air-routes data set:

    g.withSack(0).
      V('44').
      repeat(outE('route').sack(sum).by('dist').inV().simplePath()).
      times(2).
      where(sack().is(lt(500))).
      path().
        by('code').
        by('dist').
      limit(2)
    

    which yields:

    1   path[SAF, 369, PHX, 110, TUS]
    2   path[SAF, 369, PHX, 119, FLG]
    

    To use the math step requires just a little more work:

    Let's first just see how the math step works in such a case via a query to take the difference between some route distances:

    g.V('44').
      outE('route').as('a').inV().
      outE('route').as('b').inV().
      project('b','a','diff').
        by(select('b').values('dist')).
        by(select('a').values('dist')).
        by(math('b - a').by('dist')).
      limit(3)
    

    which yields:

    1   {'b': 1185, 'a': 549, 'diff': 636.0}
    2   {'b': 6257, 'a': 549, 'diff': 5708.0}
    3   {'b': 8053, 'a': 549, 'diff': 7504.0}
    

    we can now refine the query to find routes where the difference is less than 100.

    g.V('44').
      outE('route').as('a').inV().
      outE('route').as('b').inV().
      where(math('b - a').by('dist').is(lt(100))).
      path().
        by('code').
        by('dist').
      limit(3)
    

    which gives us:

    1   path[SAF, 549, DFW, 430, MEM]
    2   path[SAF, 549, DFW, 461, MCI]
    3   path[SAF, 549, DFW, 550, STL]
    

    you can also use the absolute value in the calculation if preferred:

    g.V('44').
      outE('route').as('a').inV().
      outE('route').as('b').inV().
      where(math('abs(b - a)').by('dist').is(lt(100))).
      path().
        by('code').
        by('dist').
      limit(3)