0

I am grouping vertices by any number of group parameters and I expect the resut to be sorted by those parameters.

Simple test data

g.addV("machine").property("type","PC").property("age",2)
g.addV("machine").property("type","PC").property("age",11)
g.addV("machine").property("type","Mac").property("age",2)
g.addV("machine").property("type","Mac").property("age",2)
g.addV("machine").property("type","Mac").property("age",11)

My prefered output format should look like:

==>[{age=2, type=Mac}]=[{type=[Mac], age=[2]}, {type=[Mac], age=[2]}]
==>[{age=2, type=PC}]=[{type=[PC], age=[2]}]
==>[{age=11, type=Mac}]=[{type=[Mac], age=[11]}]
==>[{age=11, type=PC}]=[{type=[PC], age=[11]}]

or

==>[2, Mac]=[{type=[Mac], age=[2]}, {type=[Mac], age=[2]}]
==>[2, PC]=[{type=[PC], age=[2]}]
==>[11, Mac]=[{type=[Mac], age=[11]}]
==>[11, PC]=[{type=[PC], age=[11]}]

Simply saying: passed grouping parameters and result vertices should be separated.

user3757753
  • 41
  • 2
  • 7

2 Answers2

2

Gremlin doesn't impose a particular order to the results of traversals. You can rely on the underlying graph implementation and its order semantics but it's often best to just be explicit with the ordering when you can. For that reason I do my group() on an ordered list of properties:

gremlin> g.V().hasLabel("machine").
......1>   group().
......2>     by(properties('age','type').order().by(key).value().fold()).
......3>   order(local).
......4>     by(select(keys).limit(local,1)).
......5>     by(select(keys).tail(local)).next()
==>[2, Mac]=[v[6], v[9]]
==>[2, PC]=[v[0]]
==>[11, Mac]=[v[12]]
==>[11, PC]=[v[3]]

which ensures the "age" comes before the "type" and then I can apply a local order to the resulting Map by just picking apart that property list with limit(), tail(), etc.

stephen mallette
  • 45,298
  • 5
  • 67
  • 135
  • In this example it will be sorted by age and then by type because 'a' < 't', I was thinking about passing the order explicitly, but thank you anyway. – user3757753 Dec 06 '21 at 17:36
  • the order of the values in the `Map` have nothing to do with `a < t` - that is just the order that the items in the `List` key are bound to be. Having a dependable order there enables you to actually choose the order in lines 3 - 5. Want to do "t" first just reverse lines 4 and 5. – stephen mallette Dec 06 '21 at 18:45
  • just realized my last sentence was a little cryptic. i meant: Want to order by "type" first? Then, just reverse lines 4 and 5 – stephen mallette Dec 06 '21 at 19:04
0

I tried couple of solutions:

gremlin> g.V().hasLabel("machine").group().by('age').by(group().by('type').by(valueMap().fold())).unfold()
==>2={PC=[{type=[PC], age=[2]}], Mac=[{type=[Mac], age=[2]}, {type=[Mac], age=[2]}]}
==>11={PC=[{type=[PC], age=[11]}], Mac=[{type=[Mac], age=[11]}]}

This one is sorted, but requires additional postprocessing and I want to suport ordering by any number of parameters in my application logic.

The format is better but not sorted:

gremlin> g.V().hasLabel("machine").order().by("age").by("type").group().by(project("age", "type").by("age").by("type").fold()).by(valueMap().fold()).unfold()
==>[{age=11, type=Mac}]=[{type=[Mac], age=[11]}]
==>[{age=2, type=PC}]=[{type=[PC], age=[2]}]
==>[{age=2, type=Mac}]=[{type=[Mac], age=[2]}, {type=[Mac], age=[2]}]
==>[{age=11, type=PC}]=[{type=[PC], age=[11]}]

The order of group params is not corect, the age should be first:

gremlin> g.V().hasLabel("machine").order().by("age").by("type").group().by(values("age", "type").fold()).by(valueMap().fold()).unfold()
==>[Mac, 2]=[{type=[Mac], age=[2]}, {type=[Mac], age=[2]}]
==>[PC, 2]=[{type=[PC], age=[2]}]
==>[PC, 11]=[{type=[PC], age=[11]}]
==>[Mac, 11]=[{type=[Mac], age=[11]}]

But none of the solutions is what I expected.

user3757753
  • 41
  • 2
  • 7