5

The Unit test code from the simplegraph-core testsuite below displays the region count of airports but it is not ordered as I would have expected.

The result starts with:

NZ-BOP=  3
MZ-A=  1
MZ-B=  1
IN-TN=  5
MZ-N=  1
PW-004=  1
MZ-I=  2
BS-FP=  1
IN-TR=  1
MZ-T=  1
BJ-AQ=  1
GB-ENG= 27

I looked into

and searched for "GroupCount" in questions tagged gremlin to no avail

What is necessary to fix the ordering?

Unit Test see also https://github.com/BITPlan/com.bitplan.simplegraph/blob/master/simplegraph-core/src/test/java/com/bitplan/simplegraph/core/TestTinkerPop3.java

  @Test
  public void testSortedGroupCount() throws Exception {
    Graph graph = getAirRoutes();
    GraphTraversalSource g = graph.traversal();
    Map<Object, Long> counts = g.V().hasLabel("airport").groupCount()
        .by("region").order().by(Order.decr).next();
    assertEquals(1473, counts.size());
    for (Object key : counts.keySet()) {
      System.out.println(String.format("%s=%3d", key, counts.get(key)));
    }
  }
Wolfgang Fahl
  • 15,016
  • 11
  • 93
  • 186

2 Answers2

7

You need to order the values with local scoping:

g.V().hasLabel("airport").
  groupCount().
    by("region").
  order(local).
    by(values, Order.decr)

With local scoping you order within the current traverser (i.e. order the contents of each Map in the traversal).

  @Test
  public void testSortedGroupCount() throws Exception {
    Graph graph = getAirRoutes();
    GraphTraversalSource g = graph.traversal();
    Map<Object, Long> counts = g.V().hasLabel("airport").groupCount()
        .by("region").order(Scope.local).by(Column.values,Order.decr).next();
    // https://stackoverflow.com/a/49361250/1497139
    assertEquals(1473, counts.size());
    assertEquals("LinkedHashMap",counts.getClass().getSimpleName());
    debug=true;
    if (debug)
      for (Object key : counts.keySet()) {
        System.out.println(String.format("%s=%3d", key, counts.get(key)));
      }

  }

will then show:

US-AK=149
AU-QLD= 50
CA-ON= 46
CA-QC= 44
PF-U-A= 30
US-CA= 29
Wolfgang Fahl
  • 15,016
  • 11
  • 93
  • 186
stephen mallette
  • 45,298
  • 5
  • 67
  • 135
  • This is the groovy solution. I tried to translate this to java and only found the Scope.local for the order(...) part. for by() I didn't find a two parameter function that fits your answer. Only doing have of your proposal leads to a class cast exception. See the modified testcase I just checked in. – Wolfgang Fahl Mar 19 '18 at 14:08
  • it's not a "Groovy" answer really. Static imports are a construct of Java as well as groovy so there is nothing particular to groovy there. you need `org.apache.tinkerpop.gremlin.structure.Column` for `values`. Here's the overload of `by()` you would be using: http://tinkerpop.apache.org/javadocs/current/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#by-java.util.function.Function-java.util.Comparator- – stephen mallette Mar 19 '18 at 14:15
  • I have almost this exact example in the tutorial/book in case it helps http://kelvinlawrence.net/book/Gremlin-Graph-Guide.html#countrydist – Kelvin Lawrence Mar 19 '18 at 18:27
0

Using the Gremlin language only, you can do it using the unfold method. This may be useful if you need to run your query by the REST API.

g.V()
  .hasLabel("airport")
  .values("region")
  .groupCount()
  .unfold()
  .order()
  .by(values)
Thiago Mata
  • 2,825
  • 33
  • 32