Augment vertices with depth/loop/level in a repeat

201 views
Skip to first unread message

Guy Ellis

unread,
Apr 14, 2017, 2:35:25 PM4/14/17
to Gremlin-users
How would I retrieve the value of the depth/loop/level with vertices in each repeat step?

i.e. If my graph had edges joining these vertices like this:

Child > Father > Grandfather > Great GrandFather

then how do I get those 4 vertices back from a query with the level of each vertex:

[
{ label: 'Child', depth: 1},
{ label: 'Father', depth: 2},
...
]

Or perhaps this would be more representative:

[
{ vertices: [ Child ], depth: 1},
{ vertices: [ Father ], depth: 2},
...
]

Message has been deleted

HadoopMarc

unread,
Apr 14, 2017, 4:23:48 PM4/14/17
to Gremlin-users
Hi Guy,

Maybe someone comes up with a oneliner, but this one does the job:

gremlin> g=TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin
> g.V(1).out().out().in().path()
==>[v[1],v[4],v[5],v[4]]
==>[v[1],v[4],v[3],v[1]]
==>[v[1],v[4],v[3],v[4]]
==>[v[1],v[4],v[3],v[6]]

// assign the first traversal to p
gremlin
> p=g.V(1).out().out().in().path().by(label()).next()
==>person
==>person
==>software
==>person
gremlin
> (1..p.size()-1).stream().map{[depth:it, label:p[it]]}.collect()
==>[depth:1,label:person]
==>[depth:2,label:software]
==>[depth:3,label:person]

Cheers,   Marc


Op vrijdag 14 april 2017 20:35:25 UTC+2 schreef Guy Ellis:

Daniel Kuppitz

unread,
Apr 14, 2017, 6:50:55 PM4/14/17
to gremli...@googlegroups.com
Hi Guy,

SackStep is your friend:

Sample graph:

graph = TinkerGraph.open()

a = graph.addVertex(id, "child")
b = graph.addVertex(id, "father")
c = graph.addVertex(id, "grandfather")
d = graph.addVertex(id, "great grandfather")
e = graph.addVertex(id, "great grandmother")

a.addEdge("parent", b)
b.addEdge("parent", c)
c.addEdge("parent", d)
c.addEdge("parent", e)

g = graph.traversal()

Query:

gremlin> g.withSack(1).V("child").emit().
             repeat(out("parent").sack(sum).by(constant(1))).
           group().by(sack()).

           unfold().project("depth", "vertices").by(keys).by(values)
==>[depth:1,vertices:[v[child]]]
==>[depth:2,vertices:[v[father]]]
==>[depth:3,vertices:[v[grandfather]]]
==>[depth:4,vertices:[v[great grandfather],v[great grandmother]]]

Cheers,
Daniel


--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/3eea97f0-59ec-4dd8-8ced-6651b0a64fd3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Marko Rodriguez

unread,
Apr 14, 2017, 9:48:04 PM4/14/17
to gremli...@googlegroups.com
Or use loops() to get the depth in the repeat() structure. You would use a group(‘m’) and then cap(‘m’) the side-effect.

NOTE: I just pushed a tp32/ bug fix for times() not working nicely with loops() (the hack is in the ticket as well as an example you could leverage for yourself).
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/CA%2Bf9seX9TTo_3z_-tx8x3MMTJ1pvg7LQ35b1VMhSb%3DE15jC3OA%40mail.gmail.com.

Guy Ellis

unread,
Apr 17, 2017, 10:06:35 AM4/17/17
to Gremlin-users
Thanks Marc, Daniel, Marko! Appreciate the help!
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/3eea97f0-59ec-4dd8-8ced-6651b0a64fd3%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Guy Ellis

unread,
Apr 18, 2017, 5:15:19 PM4/18/17
to Gremlin-users
I've been experimenting with collecting all of the side-effects that I need in the sack step and I feel that I'm almost there but need a bit of help to finish it off. My objective is to bundle the depth, the previousId and the vertex in the results. This is the code I'm using:

v1 = graph.addVertex(label, 'l1', 'spike', '1324', 'myId', 'id-1');
v2 = graph.addVertex(label, 'l2', 'spike', '1324', 'myId', 'id-2');
v3 = graph.addVertex(label, 'l3', 'spike', '1324', 'myId', 'id-3');
v4 = graph.addVertex(label, 'l4', 'spike', '1324', 'myId', 'id-4');
v1.addEdge('child', v2);
v2.addEdge('child', v3);
v3.addEdge('child', v4);

bag = [depth:0, previousId:'', id:''];

addDepthToBag = { m, v -> m.depth = m.depth + v; m; };
addIdToBag = { m, v -> m.previousId = m.id; m.id = v; m; };
addVertexToBag = { m, v -> m.vertex = v; m; };

g
.withSack{bag}{it.clone()}
.V().hasLabel("l1")
.emit()
.repeat(
  out("child")
  .sack(addIdToBag)
  .by('myId')
  .sack(addDepthToBag)
  .by(constant(1))
  .sack(addVertexToBag)
)
.sack()



And this is the result in a JavaScript array in the tool that I'm using to retrieve it:

[ { "depth": 0, "previousId": "", "id": "" }, { "depth": 1, "previousId": "", "id": "id-2", "vertex": { "id": 692232, "label": "l2", "type": "vertex", "properties": { "myId": [ { "id": "hq0x-eu4o-12px", "value": "id-2" } ], "spike": [ { "id": "hpmp-eu4o-11xh", "value": "1324" } ] } } }, { "depth": 2, "previousId": "id-2", "id": "id-3", "vertex": { "id": 626816, "label": "l3", "type": "vertex", "properties": { "myId": [ { "id": "g7io-dfnk-12px", "value": "id-3" } ], "spike": [ { "id": "g74g-dfnk-11xh", "value": "1324" } ] } } }, { "depth": 3, "previousId": "id-3", "id": "id-4", "vertex": { "id": 639224, "label": "l4", "type": "vertex", "properties": { "myId": [ { "id": "gwtb-dp88-12px", "value": "id-4" } ], "spike": [ { "id": "gwf3-dp88-11xh", "value": "1324" } ] } } } ]


My problem is adding the first vertex etc. to the sack.

Robert Dale

unread,
Apr 19, 2017, 12:08:17 AM4/19/17
to Gremlin-users
You'll need to capture the first vertex with sack just like the following vertices.

g.withSack{bag}{it.clone()}.
V().hasLabel("l1").
sack(addIdToBag).
by('myId').
sack
(addDepthToBag).
by(constant(1)).
sack
(addVertexToBag).

emit
().

repeat
(
out("child").
sack
(addIdToBag).
by('myId').
sack
(addDepthToBag).
by(constant(1)).
sack
(addVertexToBag)).sack()

HadoopMarc

unread,
Apr 19, 2017, 8:55:19 AM4/19/17
to Gremlin-users
Hi Guy and Robert,

And what happens if you put a single sackby, sackby, sackby sequence between the emit() and the repeat() ?  Given the emit/repeat semantics you would expect that to work (you only specify the emit once that get both the first and later vertices).

Cheers,    Marc

Op woensdag 19 april 2017 06:08:17 UTC+2 schreef Robert Dale:

Guy Ellis

unread,
Apr 19, 2017, 9:51:45 AM4/19/17
to Gremlin-users
@Robert - that works perfectly! You are Wednesday's hero!

@Marc - when I try that I get a null pointer exception. If I understood you correctly this is how I modified Robert's code:

g
.withSack{bag}{it.clone()}
.V().hasLabel("l1")
.emit()
.sack(addIdToBag)
.by('myId')
.sack(addDepthToBag)
.by(constant(1))
.sack(addVertexToBag)
.repeat(
  out("child")
  .sack(addIdToBag)
  .by('myId')
  .sack(addDepthToBag)
  .by(constant(1))
  .sack(addVertexToBag)
)
.sack()

And this is the error:

java.lang.NullPointerException

at org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep.standardAlgorithm(RepeatStep.java:185)

at org.apache.tinkerpop.gremlin.process.traversal.step.util.ComputerAwareStep.processNextStart(ComputerAwareStep.java:46)

at org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep.hasNext(AbstractStep.java:143)

at org.apache.tinkerpop.gremlin.process.traversal.step.util.ExpandableStepIterator.next(ExpandableStepIterator.java:50)

at org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectStep.processNextStart(SideEffectStep.java:38)

at org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep.hasNext(AbstractStep.java:143)

HadoopMarc

unread,
Apr 19, 2017, 10:07:44 AM4/19/17
to Gremlin-users
Hi Guy,

Good that it works, maybe we need @DKuppitz to get rid of the code duplication. On second sight, I think you can just take the sack filling steps out of the repeat loop and place them directly after the repeat step and before the final .sack() get step. In that position, the sack filling steps should see all emitted traversers. Just for completeness ...

Cheers,   Marc

Op woensdag 19 april 2017 15:51:45 UTC+2 schreef Guy Ellis:

Guy Ellis

unread,
Apr 21, 2017, 9:33:31 AM4/21/17
to Gremlin-users
Is there anyway that the attributes (fields) of the vertices can be augmented in-situ (i.e. not persisted to graph) during this process so that the output can be used to continue the traversal?

Robert Dale

unread,
Apr 21, 2017, 3:48:12 PM4/21/17
to gremli...@googlegroups.com

Rollback the transaction?


For more options, visit https://groups.google.com/d/optout.
--
Robert Dale

Daniel Kuppitz

unread,
Apr 23, 2017, 3:46:54 AM4/23/17
to gremli...@googlegroups.com
Perhaps use an OLAP job (which seems like a good fit anyways). You'll need a custom vertex program to store the new property, but it will only be stored in the resulting HadoopGraph, not in the underlying original graph.

Cheers,,
Daniel


To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/0174ffcc-9818-4bc6-843b-4b9df19c1ce4%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages