[NOVICE] Gremlin find adjacent vertices efficiently

293 views
Skip to first unread message

casper...@woodwing.com

unread,
Apr 8, 2015, 12:47:47 PM4/8/15
to gremli...@googlegroups.com
I want to query all nodes adjacent from a certain node. Then I want to query the adjacent nodes of those nodes and so on. 
I created a gremlin query to query the nodes with a certain 'depth' and which removes duplicates:

g.v('125582').as('s1').both().loop('s1'){it.loops<=4}.dedup() 

However this is slow and I figured that it might be very inefficient. Can this be done in a better way?
Your answer is appreciated and if you need more info, please don't hesitate to ask.

Casper

Daniel Kuppitz

unread,
Apr 8, 2015, 12:50:51 PM4/8/15
to gremli...@googlegroups.com
Try to dedup within the loop:

g.v('125582').as('s1').both().dedup().loop('s1'){it.loops<=4}

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-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/8c007500-86d4-493c-ac2b-586710eb19d0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

casper...@woodwing.com

unread,
Apr 9, 2015, 3:05:57 AM4/9/15
to gremli...@googlegroups.com
Hi Daniel, thanks for your reply. Unfortunately the supplied query returns me a wrong number of vertices.

casper...@woodwing.com

unread,
Apr 9, 2015, 3:47:24 AM4/9/15
to gremli...@googlegroups.com
I've included the structure of the graph. I hope it helps.
Screen Shot 2015-04-08 at 15.20.31 3.png

Daniel Kuppitz

unread,
Apr 9, 2015, 8:02:14 AM4/9/15
to gremli...@googlegroups.com
Yea, you should also emit every element:

g.v('125582').as('s1').both().dedup().loop('s1') {it.loops<=4}

And here's another option which - I think - should be even faster:

x = [] as Set; g.v('125582').as('s1').both().except(x).store(x).loop('s1') {it.loops<=4}.iterate(); x

If that doesn't help, it would be cool if you could provide a sample graph.

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-user...@googlegroups.com.

casper...@woodwing.com

unread,
Apr 9, 2015, 8:11:29 AM4/9/15
to gremli...@googlegroups.com
Wow, that does make a huge difference in performance! Cheers!
Is it also possible to return the accompanied edges with it?

casper...@woodwing.com

unread,
Apr 9, 2015, 8:31:14 AM4/9/15
to gremli...@googlegroups.com
In addition: this query is limited to Gremlin. How could this be done in Java for Titan?

Stephen Mallette

unread,
Apr 9, 2015, 8:53:19 AM4/9/15
to gremli...@googlegroups.com
Please see this answer on SO for how to convert Gremlin Groovy to Java:


Daniel Kuppitz

unread,
Apr 9, 2015, 9:02:02 AM4/9/15
to gremli...@googlegroups.com
Is it also possible to return the accompanied edges with it?

I would use a second query to do that. Once you have your result from the first query (x), you can do:

e = [] as Set; x._().as("x").bothE().as("e").bothV().except("x").retain(x).back("e").fill(e)

Cheers,
Daniel


casper...@woodwing.com

unread,
Apr 9, 2015, 9:13:35 AM4/9/15
to gremli...@googlegroups.com
Thanks for your replies ! I learned a lot.

Daniel Kuppitz

unread,
Apr 9, 2015, 9:19:42 AM4/9/15
to gremli...@googlegroups.com
Ok, keep learning. Actually I've just been too lazy to merge the edge stuff into the first query :). Anyway, I began to wonder if it's even possible, so I had to try - and here it is:

e = [] as Set
x = [] as Set
g.v('125582').as('s1').bothE().as('e').bothV().except('s1').except(x).sideEffect { v, m -> x << v; e << m.e }.loop('s1') {it.loops<=4}.iterate()
x // contains all vertices
e // contains all edges

Cheers,
Daniel


casper...@woodwing.com

unread,
Apr 10, 2015, 2:45:38 AM4/10/15
to gremli...@googlegroups.com
Hi Daniel, thanks again for your contribution, however it seems like this query always returns the amount edges equal to the exact number of vertices
So vertices.count() == edges.count()
Studying your query I cannot really find out what could be the cause of this.

Daniel Kuppitz

unread,
Apr 10, 2015, 8:51:07 AM4/10/15
to gremli...@googlegroups.com
Can you provide a sample graph, a start vertex and the result that you expect?

Cheers,
Daniel


casper...@woodwing.com

unread,
Apr 10, 2015, 9:29:54 AM4/10/15
to gremli...@googlegroups.com
Yes of course.
This groovy code will generate a part of the graph:

g = new TinkerGraph();for ( i in 1..60 ) {def v0 = g.getVertex(i) ?: g.addVertex(i);def v1 = g.getVertex(i-1) ?: g.addVertex(i-1);def v2 = g.getVertex(i+2) ?: g.addVertex(i+2);def v3 = g.getVertex(i+3) ?: g.addVertex(i+3);g.addEdge(null, v0, v1, "r");g.addEdge(null, v0, v2, "r");g.addEdge(null, v0, v3, "r")}


Now let's say I pick vertex 32 (g.v('32')) which is in the middle of this little graph and execute your first queries I get:

gremlin> x = [] as Set; g.v('32').as('s1').both().except(x).store(x).loop('s1') {it.loops<=4}.iterate(); x.count()

==>25

gremlin> e = [] as Set; x._().as("x").bothE().as("e").bothV().except("x").retain(x).back("e").fill(e); e.count()

==>69


Now if I execute your last suggested query:

g.v('32').as('s1').bothE().as('e').bothV().except('s1').except(x).sideEffect { v, m -> x << v; e << m.e }.loop('s1') {it.loops<=4}.iterate(); x.count()

==>24

I get both for x.count() and e.count() 24.

I expect the same results as from the first 2 commands (these give the correct info).

Daniel Kuppitz

unread,
Apr 10, 2015, 9:59:42 AM4/10/15
to gremli...@googlegroups.com
Cool, I found the bug and my first suggestion actually returns a wrong result (it includes a few edges that were never touched during the first traversal). Here's the correct solution:

gremlin> x = [] as Set; e = [] as Set; g.v('32').as('s1').bothE().store(e).bothV().except(x).store(x).loop('s1') {it.loops<=4}.iterate()
==>null
gremlin> x.count()
==>25
gremlin> e.count()
==>63

Cheers,
Daniel


casper...@woodwing.com

unread,
Apr 10, 2015, 10:05:21 AM4/10/15
to gremli...@googlegroups.com
Thanks for your awesomeness. I was already trying something with the store command, but didn't succeed. Lots of material to learn from.
Thank you for your time!

Daniel Kuppitz

unread,
Apr 10, 2015, 10:17:07 AM4/10/15
to gremli...@googlegroups.com
And since TP2 is getting old, I thought it would be nice to see the solution in TP3:

graph = TinkerGraph.open()
g = graph.traversal(standard())

(1..60).each { def i ->
  def v0 = (g.V(i) ?: [graph.addVertex(id, i)].iterator()).next()
  def v1 = (g.V(i-1) ?: [graph.addVertex(id, i-1)].iterator()).next()
  def v2 = (g.V(i+2) ?: [graph.addVertex(id, i+2)].iterator()).next()
  def v3 = (g.V(i+3) ?: [graph.addVertex(id, i+3)].iterator()).next()
  v0.addEdge("r", v1)
  v0.addEdge("r", v2)
  v0.addEdge("r", v3)
}; null

res = g.V(32).repeat(bothE().dedup().store('e').bothV().except('x').store('x')).times(4).cap('x','e').next()

gremlin> res.x.size()
==>25
gremlin> res.e.size()
==>63

Cheers,
Daniel


Reply all
Reply to author
Forward
0 new messages