Add edges within one traversal using Gremlin - graph

we have:
g = graph.traversal()
What I what to do is like:
numV = g.V().count()
g.V().range(0,numV-1).addE('label').to(g.V().range(1,numV))
I want to add out edges between two adjacent vertices.
In my case, numV is calculated using a long code instead of simple g.V().count(), also g.V() in the second line will be replaced by a long line, so there are two questions:
How to avoid pre-compute numV? as we have already done g.V() in the second line of the code.
I tried to simplify the code like this:
g.V().as('a').range(0,numV-1).addE('label').to(select('a').range(1,numV))
but it gives me error:
The provided traverser does not map to a value
I am kind of new to Gremlin.

Let's start with a small sample graph that consists of foo and bar vertices and sequential IDs.
gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.withSack(1).
......1> addV('foo').
......2> property(id, sack()).
......3> emit().
......4> repeat(sack(sum).by(constant(1)).
......5> addV().
......6> property(label, __.constant(['foo','bar']).sample(local, 1).unfold()).
......7> property(id, sack())).
......8> times(20).
......9> valueMap(true)
==>[label:foo,id:1]
==>[label:foo,id:2]
==>[label:bar,id:3]
==>[label:foo,id:4]
==>[label:bar,id:5]
==>[label:bar,id:6]
==>[label:foo,id:7]
==>[label:foo,id:8]
==>[label:foo,id:9]
==>[label:bar,id:10]
==>[label:foo,id:11]
==>[label:bar,id:12]
==>[label:foo,id:13]
==>[label:bar,id:14]
==>[label:bar,id:15]
==>[label:foo,id:16]
==>[label:bar,id:17]
==>[label:bar,id:18]
==>[label:foo,id:19]
==>[label:foo,id:20]
==>[label:bar,id:21]
Now let's say that we want to connect all foo vertices with a baz edge; the order criteria will be the vertex id.
gremlin> g.V().hasLabel('foo').
......1> order().
......2> by(id).as('a').
......3> aggregate('x').
......4> flatMap(select('x').unfold().
......5> where(gt('a')).by(id).
......6> limit(1)).
......7> addE('baz').
......8> from('a')
==>e[0][1-baz->2]
==>e[1][2-baz->4]
==>e[2][4-baz->7]
==>e[3][7-baz->8]
==>e[4][8-baz->9]
==>e[5][9-baz->11]
==>e[6][11-baz->13]
==>e[7][13-baz->16]
==>e[8][16-baz->19]
==>e[9][19-baz->20]
I think that's pretty much the scenario you're looking for, but it's hard to tell without a provided sample graph and an expected outcome.
Also note, that you should always have an explicit order criterion (it doesn't have to be the id), otherwise TinkerPop won't guarantee a deterministic order.

Related

How stop Repeat when first results are found in Gremlin TinkerPop Graph

How can I stop traversing further down a graph using a Repeat when the first results are found?
I have tried to use an aggregate variable but it seem that the until step ignores it.
Se demo
https://gremlify.com/2gr4460avv1
I cannot get the this line to work in the until step:
sack().is(within('level'))
eg. with the following graph:
g.addV('User 0').as('0').
property(single, 'name', 'v0').
addV('User 1').as('1').
property(single, 'name', 'v1').
addV('User 2').as('2').
property(single, 'name', 'v2').
addV('User 3').as('3').
property(single, 'name', 'v3').
addV('User 4').as('4').
property(single, 'name', 'v3').
addV('Subject 1').as('5').
property(single, 'name', 's1').
addE('Trust').from('0').to('1').property("distance", 1).
addE('Trust').from('0').to('2').property("distance", 1).
addE('Trust').from('0').to('3').property("distance", 1).
addE('Trust').from('1').to('2').property("distance", 1).
addE('Trust').from('1').to('4').property("distance", 1).
addE('Audit').from('2').to('5').property("distance", 0).
addE('Trust').from('2').to('3').property("distance", 1).
addE('Audit').from('3').to('5').property("distance", 0).
addE('Trust').from('3').to('0').property("distance", 1).
addE('Audit').from('4').to('2').property("distance", 0)
Query:
g.withSack(0).V().has("name", "v0").
repeat(outE("Trust", "Audit").as("e").sack(sum).by('distance').
inV().simplePath().
choose(
select("e").hasLabel("Trust"),
choose(
select("e").has("distance", gte(0)),
aggregate('allow'),
aggregate('distrust')
)
)
).
until(
has('name', 's1').
or().
sack().is(gte(3)).
or().
sack().is(within('level')).
or().
where(within('distrust'))
).
has('name', 's1').
sack(sum).by(constant(1)).sack().aggregate('level').
path()
Result:
==>[v[0],e[13][0-Trust->4],v[4],e[17][4-Audit->10],v[10],2]
==>[v[0],e[14][0-Trust->6],v[6],e[19][6-Audit->10],v[10],2]
==>[v[0],e[12][0-Trust->2],v[2],e[16][2-Trust->8],v[8],e[21][8-Audit->10],v[10],3]
==>[v[0],e[12][0-Trust->2],v[2],e[15][2-Trust->4],v[4],e[17][4-Audit->10],v[10],3]
==>[v[0],e[13][0-Trust->4],v[4],e[18][4-Trust->6],v[6],e[19][6-Audit->10],v[10],3]
But I want the gremlin to stop at the level of the first result. e.g. so the result should look like this.
==>[v[0],e[13][0-Trust->4],v[4],e[17][4-Audit->10],v[10],2]
==>[v[0],e[14][0-Trust->6],v[6],e[19][6-Audit->10],v[10],2]
The query should find one or more result at the same degree if they exist, then stop looking for longer routes.
The idea is that in a very large graph the query stops early if it finds one or more results at the same degree.
PS! withComputer() would be nice, but I need to filter untrusted user away from the route calculation dynamically and cannot see how this can be done using the shortestPath() function.
I did not yet have time to try with your data set, but here is an example that uses a data set I had to hand that shows how to end a repeat based on the sack value having exceeded a given threshold.
gremlin> g.withSideEffect('level',3000).
......1> withSack(0).
......2> V(44).
......3> repeat(outE().sack(sum).by('dist').inV().simplePath()).
......4> until(where(gt('level')).by(sack()).by().or().loops().is(3)).
......5> path().
......6> by('code').
......7> by('dist').
......8> limit(3)
==>[SAF,549,DFW,4736,LHR]
==>[SAF,549,DFW,4933,CDG]
==>[SAF,549,DFW,5127,FRA]
I added the loops test just to avoid any runaway queries, but it is not needed if the dataset is well understood to not have that potential.
gremlin> g.withSideEffect('level',3000).
......1> withSack(0).
......2> V(44).
......3> repeat(outE().sack(sum).by('dist').inV().simplePath()).
......4> until(where(gt('level')).by(sack()).by()).
......5> path().
......6> by('code').
......7> by('dist').
......8> limit(3)
==>[SAF,549,DFW,4736,LHR]
==>[SAF,549,DFW,4933,CDG]
==>[SAF,549,DFW,5127,FRA]
The key takeaway here is that where(predicate('string')) is a special case of where such that the string is treated as the name of a "variable" and not a literal string, as in where(within('my-list')).
Note also that if all you really want is a depth counter, you can just use loops and not worry about managing a sack.
Here is one last example, that adds an and step to the until. This will stop when distances greater than 3000 are found AND those distances are between 3001 and 4500 miles, or loops gets to 3.
gremlin> g.withSideEffect('level',3000).
......1> withSack(0).
......2> V(44).
......3> repeat(outE().sack(sum).by('dist').inV().simplePath()).
......4> until(and((where(gt('level')).by(sack()).by()),
......5> sack().is(between(3001,4500))).
......6> or().loops().is(3)).
......7> path().
......8> by('code').
......9> by('dist').
.....10> limit(3)
==>[SAF,549,DFW,3368,LIM]
==>[SAF,549,DFW,3702,OGG]
==>[SAF,549,DFW,3733,KEF]

Check the sack() value in a gremlin query

We have a query to find the possible paths to a node. We represented ABC paths with numbers as shown in the table and we are using bitwise and operation to see available paths to a node. We are repeating the query if there is at least one available path (A, B or C) to a node (values('availablePath').is(gt(0))). However, we want to stop the query if the sack value is 0 since it does not make sense to continue traversing after the Node 3 because sack value is 0, which means that you can not access node 3 by A, B or C paths. Is there a way to get the sack value and stop traversing if it is 0?
Our query is:
g.withSack(7).
V().has('id','1')
local(
repeat(bothE().where(values('availablePath').is(gt(0))).
sack{f,l -> f & l}.
by('availablePath').
otherV().
simplePath().as('node')).
emit().
sack().as('path')).
select('node','path').
by().
by().
dedup()
Sample graph creation query:
g.addV('node').property('id','1').as('1')
.addV('node').property('id','2').as('2')
.addV('node').property('id','3').as('3')
.addV('node').property('id','4').as('4')
.addE('edge').property('availablePath',3).from('1').to('2').as('edge1')
.addE('edge').property('availablePath',4).from('2').to('3').as('edge2')
.addE('edge').property('availablePath',7).from('3').to('4').as('edge3')
Traversal begins from node 1.
GRAPH
TABLE
You can test the sack value inside the where step as follows:
gremlin> g.withSack(7).
......1> V().has('id','1').
......2> local(
......3> repeat(bothE().where(values('availablePath').is(gt(0)).and().sack().is(gt(0))).
......4> sack{f,l -> f & l}.
......5> by('availablePath').
......6> otherV().
......7> simplePath().as('node')).
......8> emit().
......9> sack().as('path')).
.....10> select('node','path').
.....11> by().
.....12> by().
.....13> dedup()
==>[node:v[4],path:3]
==>[node:v[6],path:0]

Repeat issue traversing ordered edges in tree query

I have a graph in which a vertex has multiple edges from the same parent. I need to traverse only one of the edges based on the highest property value to create a tree.
I used "order().by" to pick the edge. Works for a one-level query. As soon I try to repeat for a tree there is an error I do not understand:
"The parent of a reducing barrier can not be repeat()-step: GroupStep([EdgeVertexStep(IN)],[FoldStep])"
The graph:
g.addV("O").property("name",'A').as('A').
addV("O").property("name",'B').as('B').
addV("O").property("name",'C').as('C').
addV("O").property("name",'D').as('D').
addV("O").property("name",'E').as('E').
addV("O").property("name",'F').as('F').
addE("R").property("ver","1").from('A').to('B').
addE("R").property("ver","2").from('A').to('B').
addE("R").property("ver","1").from('A').to('C').
addE("R").property("ver","1").from('B').to('D').
addE("R").property("ver","1").from('B').to('F')
I wish to extract a tree like:
A
B (ver=2)
D (ver=1)
F (ver=1)
C (ver=1)
My traverse query with he repeat issue:
g.V().has('name','A').
repeat(
outE('R').group().by(inV()).
select(values).unfold().
local(unfold().order().by('ver', desc).limit(1).inV())).
times(3).
emit().tree().toList()
Result: "The parent of a reducing barrier can not be repeat()-step: GroupStep([EdgeVertexStep(IN)],[FoldStep])"
On Gremlify: https://gremlify.com/r3ubmv3gt8/4
Any help is greatly appreciated.
Thank you,
Andrew
The problem is that the you cannot use group inside of a repeat loop in this way (when used with emit), unless you use the side effect form, where group is given a label such as group('x'). You will need to refactor your query taking that into account.
Perhaps, something along these lines:
gremlin> g.V().has('name','A').
......1> repeat(map(outE('R').
......2> order().
......3> by('ver',desc).
......4> limit(1).
......5> inV())).
......6> times(3).
......7> emit().tree()
==>[v[61415]:[v[61417]:[v[61421]:[]]]]
Alternatively, if you know the maximum depth, you can remove emit and probably tree and just use path
gremlin> g.V().has('name','A').
......1> repeat(flatMap(outE('R').
......2> order().
......3> by('ver',desc).
......4> limit(1).
......5> inV())).
......6> times(2).
......7> path()
==>[v[61415],v[61417],v[61421]]
Lastly, if the depth is unknown but you want to set an upper bound you can slightly change the termination condition:
gremlin> g.V().has('name','A').
......1> repeat(flatMap(outE('R').
......2> order().
......3> by('ver',desc).
......4> limit(1).
......5> inV())).
......6> until(__.not(out('R')).or().loops().is(3)).
......7> path()
==>[v[61415],v[61417],v[61421]]
UPDATED 2022-01-03 to add:
Based on the additional information provided in the comments and updated question, I am adding an additional example. Rather than return a tree this query returns a new subgraph that represents the structure traversed with only the highest version edge between any two adjacent vertices present. I used the Gremlin Console to demonstrate that it works.
gremlin> g.V().has('name','A').
......1> repeat(outE('R').
......2> group('x').
......3> by(loops()).
......4> by(group().
......5> by(inV()).
......6> by(order().by('ver',desc).limit(1))).inV()).
......7> until(__.not(out())).
......8> cap('x').unfold().select(values).unfold().select(values).subgraph('s').cap('s')
==>tinkergraph[vertices:5 edges:4]
We can create a new traversal for this subgraph and explore it:
gremlin> g2=g.V().has('name','A').
......1> repeat(outE('R').
......2> group('x').
......3> by(loops()).
......4> by(group().
......5> by(inV()).
......6> by(order().by('ver',desc).limit(1))).inV()).
......7> until(__.not(out())).
......8> cap('x').unfold().select(values).unfold().select(values).subgraph('s').cap('s').next();[]
==>tinkergraph[vertices:5 edges:4]
gremlin> g3=g2.traversal()
gremlin> g3.V().outE().inV().path().by('name').by('ver')
==>[A,2,B]
==>[A,1,C]
==>[B,1,F]
==>[B,1,D]
gremlin> g3.V().has('name','A').repeat(outE('R').inV()).until(__.not(out())).path().by('name').by('ver')
==>[A,1,C]
==>[A,2,B,1,F]
==>[A,2,B,1,D]
FURTHER UPDATED
Right after I posted that last update, I realized a different approach using flatMap might do the trick
gremlin> g.V().has('name','A').
......1> repeat(
......2> flatMap(
......3> out().
......4> dedup().
......5> local(
......6> inE().
......7> order().
......8> by('ver',desc).
......9> limit(1))).
.....10> inV()).
.....11> until(__.not(out())).
.....12> path().
.....13> by('name').
.....14> by('ver')
==>[A,1,C]
==>[A,2,B,1,F]
==>[A,2,B,1,D]
and to produce a tree
gremlin> g.V().has('name','A').
......1> repeat(
......2> flatMap(
......3> out().
......4> dedup().
......5> local(
......6> inE().
......7> order().
......8> by('ver',desc).
......9> limit(1))).
.....10> inV()).
.....11> until(__.not(out())).tree()
==>[v[0]:[e[13][0-R->2]:[v[2]:[e[16][2-R->10]:[v[10]:[]],e[15][2-R->6]:[v[6]:[]]]],e[14][0-R->4]:[v[4]:[]]]]

Decision Tree query in Gremlin

I have simplified a decision graph. It starts with begin vertex and ends with decision. My aim is to calculate the sum of a score (score associated with vertex) while traveling different paths (to reach decision vertex).
The input to Graph is JSON.
Edges between vertices contain variables and values which can be checked from the input JSON.
Example input JSON :{ "age":45,"income_source":"job" }
Output is the sum of the scores [10 + 15 + 22] = 47
In Neo4j a Cypher query allows you to pass JSON input as query parameters but I do not know how this can be done in Gremlin.
Graph link : https://gremlify.com/nwgxqs5h7zh/
g.addV('begin').as('beg').
addV('decision').property('score',0).property('decision_code',"minor").as('dec0').
addV('age').property('score',10).as('age10').
addV('age').property('score',20).as('age20').
addV('salary').property('score',15).as('sal15').
addV('salary').property('score',25).as('sal25').
addV('salary').property('score',18).as('sal18').
addV('salary').property('score',30).as('sal30').
addV('decision').property('score',22).property('decision_code',"decision_22").as('dec22').
addV('decision').property('score',45).property('decision_code',"decision_45").as('dec45').
addV('decision').property('score',18).property('decision_code',"decision_18").as('dec18').
addV('decision').property('score',30).property('decision_code',"decision_30").as('dec30').
addE('relation').property('var',"age").property('val',"").property('min',"10").property('max',"18").from('beg').to('dec0').
addE('relation').property('var',"age").property('val',"").property('min',"19").property('max',"48").from('beg').to('age10').
addE('relation').property('var',"age").property('val',"").property('min',"49").property('max',"80").from('beg').to('age20').
addE('relation').property('var',"income_source").property('val',"job").property('min',"-1").property('max',"-1").from('age10').to('sal15').
addE('relation').property('var',"income_source").property('val',"buisness").property('min',"-1").property('max',"-1").from('age10').to('sal25').
addE('relation').property('var',"income_source").property('val',"job").property('min',"-1").property('max',"-1").from('age20').to('sal18').
addE('relation').property('var',"income_source").property('val',"buisness").property('min',"-1").property('max',"-1").from('age20').to('sal30').
addE('relation').property('var',"").property('val',"").property('min',"-1").property('max',"-1").from('sal15').to('dec22').
addE('relation').property('var',"").property('val',"").property('min',"-1").property('max',"-1").from('sal25').to('dec45').
addE('relation').property('var',"").property('val',"").property('min',"-1").property('max',"-1").from('sal18').to('dec18').
addE('relation').property('var',"").property('val',"").property('min',"-1").property('max',"-1").from('sal30').to('dec30')
There is an issue with lt, gt, inside, between predicate. It only accepts number not any thing which evaluates to number.
g.inject(['val1':10,'val2':15]).as('data').V().
where(select('data').select('val1').is(lt(select('data').values('val2'))))
Above query fails Cannot compare '10' (Integer) and '[SelectOneStep(last,data), PropertiesStep([val2],value)]'... Due to this issue below query also fails.
g.withSack(0).inject(['age':45,'source':'job']).as('data').
V().hasLabel('begin').
repeat(outE().as('e').where(select('data').select(select('e').values('var')).is(eq(select('e').values('val')).or(inside(select('e').values('min'),select('e').values('max'))))).inV().sack(sum).by('score')).
until(hasLabel('decision')).project('final_score','path').by(sack()).by(path())
Please let me know if this problem can be modeled in different way to achieve same output score
Thank you for your time.
I have converted input JSON as a List. The ordering of element in this list is important. It decides, the level at which the traversal will
compare which element from the list.
g.withSack(0).
inject(["age", 45, "income_source", "job"]).as("input").
# initialized sack and input List
V().hasLabel("begin").
outE().as('a').local(and(
select("input").unfold().range(0, 1).as("temp").
select("a").values("var").where(eq("temp")), # FILTER property "var"
select("input").unfold().range(1, 2).as("temp").
select("a").values("max").where(gte("temp")).
select("a").values("min").where(lte("temp")))). # FILTER by age from input.
inV().sack(sum).by("score").
outE().as("b").local(and(
select("input").unfold().range(2, 3).as("temp").
select("b").values("var").where(eq("temp")), # FILTER property "var"
select("input").unfold().range(3, 4).as("temp").
select("b").values("val").where(eq("temp")))). # FILTER property val
inV().sack(sum).by("score").
out().sack(sum).by("score").
sack()
You can inject a map into a Gremlin query which essentially has the same shape as your JSON document. The basic building blocks for the first part of the query will look something like this, which I tested using your data and TinkerGraph.
gremlin> g.inject(['age':45,'source':'job']).as('data').
......1> V().hasLabel('begin').
......2> outE().as('e1').
......3> where(gte('e1')).
......4> by(select('data').select('age')).
......5> by('min').
......6> where(lte('e1')).
......7> by(select('data').select('age')).
......8> by('max').
......9> valueMap()
==>[min:19,max:48,var:age]
The next step is to find the edges that have the job tag.
gremlin> g.inject(['age':45,'source':'job']).as('data').
......1> V().hasLabel('begin').
......2> outE().as('e1').
......3> where(gte('e1')).
......4> by(select('data').select('age')).
......5> by('min').
......6> where(lte('e1')).
......7> by(select('data').select('age')).
......8> by('max').
......9> inV().
.....10> outE().as('e2').
.....11> where(eq('e2')).
.....12> by(select('data').select('source')).
.....13> by('val').valueMap()
==>[val:job,var:income_source]
All we need to do now is traverse to the final node and calculate the sum.
gremlin> g.withSack(0).
......1> inject(['age':45,'source':'job']).as('data').
......2> V().hasLabel('begin').
......3> outE().as('e1').
......4> where(gte('e1')).
......5> by(select('data').select('age')).
......6> by('min').
......7> where(lte('e1')).
......8> by(select('data').select('age')).
......9> by('max').
.....10> inV().
.....11> sack(sum).
.....12> by('score').
.....13> outE().as('e2').
.....14> where(eq('e2')).
.....15> by(select('data').select('source')).
.....16> by('val').
.....17> inV().
.....18> sack(sum).
.....19> by('score').
.....20> out().
.....21> sack(sum).
.....22> by('score').
.....23> sack()
==>47

Gremlin find lightest path between vertices

I am pretty new to Gremlin and I am trying to find within my graph the lightest paths from source_id vertex to target_id vertex. (On some edges I have weights and on others I don't)
To get the shortest path I can with:
g.V()
.has("id", source_id)
.repeat(outV().simplePath())
.until(has("id", target_id))
.path()
.limit(3)
.toList()
)
I have read this reference book
and it suggested to use something like:
g.V()
.has("id", source_id)
.repeat(out()).simplePath())
.until(has("id", target_id))
.path()
.by(coalesce(values("weight"), constant(0.0)))
.limit(limit)
.toList()
)
This is not working and returning the weights of the paths,
how can I achieve this with Gremlin? should first get the paths, calculate their weights and then sort them by the weights? there must be an easier and intuitive way for this basic need. (if it were neo4j I could just run Dijkstra's algorithm)
Would appreciate some help here,
thanks
I created the following example graph to help illustrate this answer.
gremlin> g.addV('A').as('a').
......1> addV('B').as('b').
......2> addV('C').as('c').
......3> addV('D').as('d').
......4> addV('E').as('e').
......5> addV('F').as('f').
......6> addV('G').as('g').
......7> addV('H').as('h').
......8> addV('Z').as('z').
......9> addE('knows').from('a').to('b').property('weight',0.2).
.....10> addE('knows').from('a').to('c').property('weight',0.5).
.....11> addE('knows').from('a').to('f').property('weight',3.5).
.....12> addE('knows').from('b').to('c').property('weight',0.1).
.....13> addE('knows').from('c').to('d').property('weight',0.3).
.....14> addE('knows').from('c').to('e').property('weight',0.2).
.....15> addE('knows').from('c').to('f').
.....16> addE('knows').from('d').to('f').property('weight',0.1).
.....17> addE('knows').from('d').to('g').property('weight',2.0).
.....18> addE('knows').from('f').to('g').property('weight',0.9).
.....19> addE('knows').from('f').to('h').property('weight',0.3).
.....20> addE('knows').from('f').to('z').property('weight',0.1).
.....21> addE('knows').from('h').to('z').property('weight',0.2).iterate()
The following routes exist from A to Z (regardless of edge weight).
gremlin> g.V().hasLabel('A').
......1> repeat(outE().inV().simplePath()).until(hasLabel('Z')).path().by(label)
==>[A,knows,F,knows,Z]
==>[A,knows,F,knows,H,knows,Z]
==>[A,knows,C,knows,F,knows,Z]
==>[A,knows,B,knows,C,knows,F,knows,Z]
==>[A,knows,C,knows,D,knows,F,knows,Z]
==>[A,knows,C,knows,F,knows,H,knows,Z]
==>[A,knows,B,knows,C,knows,D,knows,F,knows,Z]
==>[A,knows,B,knows,C,knows,F,knows,H,knows,Z]
==>[A,knows,C,knows,D,knows,F,knows,H,knows,Z]
==>[A,knows,B,knows,C,knows,D,knows,F,knows,H,knows,Z]
Note that one of the edges does not have a weight. We can find the paths with the lightest weights (where no weight is treated as a zero value) as follows:
gremlin> g.withSack(0).V().
......1> hasLabel('A').
......2> repeat(outE().sack(sum).by(coalesce(values('weight'),constant(0))).inV()).
......3> until(hasLabel('Z')).
......4> order().by(sack(),asc).
......5> path().
......6> by(label)
==>[A,knows,B,knows,C,knows,F,knows,Z]
==>[A,knows,C,knows,F,knows,Z]
==>[A,knows,B,knows,C,knows,D,knows,F,knows,Z]
==>[A,knows,B,knows,C,knows,F,knows,H,knows,Z]
==>[A,knows,C,knows,D,knows,F,knows,Z]
==>[A,knows,C,knows,F,knows,H,knows,Z]
==>[A,knows,B,knows,C,knows,D,knows,F,knows,H,knows,Z]
==>[A,knows,C,knows,D,knows,F,knows,H,knows,Z]
==>[A,knows,F,knows,Z]
==>[A,knows,F,knows,H,knows,Z]
Just to prove that things are working as expected we can add the total weight value to each result.
gremlin> g.withSack(0).V().
......1> hasLabel('A').
......2> repeat(outE().sack(sum).by(coalesce(values('weight'),constant(0))).inV()).
......3> until(hasLabel('Z')).
......4> order().by(sack(),asc).
......5> local(
......6> union(
......7> path().
......8> by(label),
......9> sack()).
.....10> fold())
==>[[A,knows,B,knows,C,knows,F,knows,Z],0.4]
==>[[A,knows,C,knows,F,knows,Z],0.6]
==>[[A,knows,B,knows,C,knows,D,knows,F,knows,Z],0.8]
==>[[A,knows,B,knows,C,knows,F,knows,H,knows,Z],0.8]
==>[[A,knows,C,knows,D,knows,F,knows,Z],1.0]
==>[[A,knows,C,knows,F,knows,H,knows,Z],1.0]
==>[[A,knows,B,knows,C,knows,D,knows,F,knows,H,knows,Z],1.2]
==>[[A,knows,C,knows,D,knows,F,knows,H,knows,Z],1.4]
==>[[A,knows,F,knows,Z],3.6]
==>[[A,knows,F,knows,H,knows,Z],4.0]

Resources