Search code examples
javagremlin

translating gremlin-groovy to jave e.g. it keyword / usage of sum() step


https://groups.google.com/forum/#!topic/gremlin-users/UZMD1qp5mfg discusses a group by example using the script:

gremlin> g.V.outE.groupBy{it.inV.next().name}{it.weight}{it.sum().doubleValue()}.cap.orderMap(T.decr)

based on the modern example graph: tinkerpop modern example graph

I'd like to try this out using Java but:

  1. I don't know how the "it" keyword is implemented in java.
  2. the cap step needs two parameters in java
  3. There seems to be no orderMap as of Tinkerpop 3.4.0

First I only got as far as:

    // g.V.outE.groupBy{it.inV.next().name}{it.weight}{it.sum().doubleValue()}.cap.orderMap(T.decr)
    GraphTraversalSource g = TinkerFactory.createModern().traversal();
    Map<Object, Object> map = g.V().outE().group().by().next();
    if (debug) {
      System.out.println(map.values().size());
      for (Entry<Object, Object> entry : map.entrySet()) {
        System.out
            .println(String.format("%s=%s", entry.getKey(), entry.getValue()));
      }
    }

giving the debug output:

6
e[7][1-knows->2]=[e[7][1-knows->2]]
e[8][1-knows->4]=[e[8][1-knows->4]]
e[9][1-created->3]=[e[9][1-created->3]]
e[10][4-created->5]=[e[10][4-created->5]]
e[11][4-created->3]=[e[11][4-created->3]]
e[12][6-created->3]=[e[12][6-created->3]]

Then I experimented a bit like this:

import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;

 /**
   * show the given map entries
   * 
   * @param map
   */
  public void showMap(String title, Map<Object, Object> map) {
    System.out.println(title + ":" + map.values().size());
    for (Entry<Object, Object> entry : map.entrySet()) {
      System.out
          .println(String.format("\t%s=%s", entry.getKey(), entry.getValue()));
    }
  }

  public void showObject(String title, Object object) {
    System.out.println(title+":"+object.toString());
  }

  @Test
  /**
   * https://groups.google.com/forum/#!topic/gremlin-users/UZMD1qp5mfg
   * https://stackoverflow.com/questions/55771036/it-keyword-in-gremlin-java
   */
  public void testGroupBy() {
    // gremlin:
    // g.V.outE.groupBy{it.inV.next().name}{it.weight}{it.sum().doubleValue()}.cap.orderMap(T.decr)
    GraphTraversalSource g = TinkerFactory.createModern().traversal();
    debug=true;
    if (debug) {
      g.V().outE().group().by().forEachRemaining(m -> showMap("by()", m));
      g.V().outE().group().by(inV().id())
          .forEachRemaining(m -> showMap("by(inV().id())", m));
      g.V().outE().group("edges").by(inV().id()).cap("edges")
      .forEachRemaining(o -> showObject("cap", o));
}

with the result:

by():6
    e[7][1-knows->2]=[e[7][1-knows->2]]
    e[8][1-knows->4]=[e[8][1-knows->4]]
    e[9][1-created->3]=[e[9][1-created->3]]
    e[10][4-created->5]=[e[10][4-created->5]]
    e[11][4-created->3]=[e[11][4-created->3]]
    e[12][6-created->3]=[e[12][6-created->3]]
by(inV().id()):4
    2=[e[7][1-knows->2]]
    3=[e[9][1-created->3], e[11][4-created->3], e[12][6-created->3]]
    4=[e[8][1-knows->4]]
    5=[e[10][4-created->5]]
cap:{2=[e[7][1-knows->2]], 3=[e[9][1-created->3], e[11][4-created->3], e[12][6-created->3]], 4=[e[8][1-knows->4]], 5=[e[10][4-created->5]]}

So it looks like the "it" can be simply left out and for the cap step the "group" has to be named. The other parts of the gremlin-groovy to Java translation I still do not understand.

How is the above script fully translated to Java?


Solution

  • In TinkerPop 3 it's as simple as:

    g.V().outE().
      group().
        by(inV().values("name")).
        by(values("weight").sum()).
      order(local).
        by(values, desc)
    

    or in full java syntax:

    import org.apache.tinkerpop.gremlin.structure.Column;
    import org.apache.tinkerpop.gremlin.process.traversal.Order;
    import org.apache.tinkerpop.gremlin.process.traversal.Scope;
    import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
    import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.*;
    import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
    
    g.V().outE().
     group().
       by(inV().values("name")).
       by(values("weight").sum()).
     order(Scope.local).
       by(Column.values, Order.desc)
    

    with the result:

    sum:{ripple=1.0, josh=1.0, lop=1.0, vadas=0.5}

    UPDATE

    To answer the question in your comment about using both vertices, it would be something like this:

    g.E().
      group().
        by(bothV().values("name").fold()).
        by(values("weight").sum()).
      order(Scope.local).
        by(Column.values, Order.desc)