Gremlin BFS enumeration including root - gremlin

I want to include the root node in the output for the following Gremlin expression:
gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.v(1).as('x').out.loop('x'){true}{true}
==>v[2]
==>v[4]
==>v[3]
==>v[5]
==>v[3]
So that the output includes v[1] as well. How can I achieve that?

Here are a couple of possible solutions in TinkerPop 2.x First one that uses store():
gremlin> x=[];g.v(1).store(x).as('x').out.loop('x'){true}{true}.store(x).iterate();x
==>v[1]
==>v[3]
==>v[2]
==>v[4]
==>v[3]
==>v[5]
Here's a second that doesn't explicitly force creation of an external variable that uses transform and a closure:
gremlin> g.v(1).transform{[it] + (it._().as('x').out.loop('x'){true}{true}.toList())}.scatter()
==>v[1]
==>v[3]
==>v[2]
==>v[4]
==>v[3]
==>v[5]
For those using TinkerPop 3.x, simply place the emit() in front of the repeat():
gremlin> g.V(1).emit().repeat(out())
==>v[1]
==>v[3]
==>v[2]
==>v[4]
==>v[5]
==>v[3]

Related

Gremlin drop deletes only the first vertex of the sub-graph

I have a graph where A is connected to B,C,D with edges.
I'm using the following to delete A and its connected vertexes.
g.V('A').
union(__(),
repeat(out()).emit()).drop()
But it deletes only A.
When I run it without the drop() it returns a list of all the sub-graph vertexes.
I'm using the tinkerpop console/server version 3.4.9.
You need to collect the results of the union step before calling drop. Here is the query slightly modified.
gremlin> g.addV('A').as('a').
......1> addV('B').as('b').
......2> addV('C').as('c').
......3> addV('D').as('d').
......4> addE('knows').from('a').to('b').
......5> addE('knows').from('b').to('c').
......6> addE('knows').from('c').to('d')
==>e[41][37-knows->38]
gremlin> g.V().hasLabel('A').
......1> union(identity(),
......2> repeat(out()).emit()).fold()
==>[v[35],v[36],v[37],v[38]]
gremlin> g.V().hasLabel('A').
......1> union(identity(),
......2> repeat(out()).emit()).fold().unfold().drop()
gremlin> g
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
Note also that this can be done without the need for a union step by moving the emit before the repeat and using store.
g.V().hasLabel('A').
emit().
repeat(store('v').out()).
cap('v').
unfold().
drop()

How to drop an edge in Gremlin?

I currently have this state of my graph database. I've SSH'ed into my EC2 instance and from there connected to my Amazon Neptune database.
g.V()
==>v[26b648fe-b972-a1b4-1642-1ef06ae42a87]
==>v[2]
==>v[6]
==>v[1]
==>v[3]
==>v[7cb648ff-2791-229a-50eb-2408938b42ba]
==>v[4]
==>v[5]
gremlin> g.E()
==>e[62b648fe-fd52-d10f-71d6-f15edd014a13][1-knows->4]
==>e[acb648ff-06b9-8526-846f-f03e5c08d6bc][6-created->3]
==>e[2cb648ff-0663-6343-2d40-ea535087771b][1-created->3]
==>e[4cb648fe-fd13-8a2b-049f-b65ddd7bd3d7][1-knows->2]
==>e[0eb648ff-0678-90d1-d77f-69b1733d4c95][4-created->5]
==>e[74b648ff-0686-3018-c0cf-2f4b15dcd4e2][4-knows->3]
gremlin> g.V().has("name", "marko").outE('knows')
==>e[4cb648fe-fd13-8a2b-049f-b65ddd7bd3d7][1-knows->2]
==>e[62b648fe-fd52-d10f-71d6-f15edd014a13][1-knows->4]
So what is 4cb648fe-fd13-8a2b-049f-b65ddd7bd3d7? Is this some kind of ID?
1 knows 4, 3, 2. How do I make it so that 1 only knows 1 and 4?
4cb648fe-fd13-8a2b-049f-b65ddd7bd3d7 is the id of the edge between 1 and 2.
If you want to drop all edge from 1 to any vertex besides 1 and 4 you can run:
g.V('1').outE('knows').where(inV().not(hasId('1', '4'))).drop()

How to use less than inside option of CHOOSE step in gremlin

.choose(values('points')
.option(lt(500), updating the vertex properties)
.option(gt(500), updating and creating new properties)
.option(none,creating new vertex ))
points is vertex property of type integer
I want to perform less than and greater than operations inside option. I am trying in the above way.Please correct me if I am wrong.
If there is any other way to perform this please let me know.
Thank you
This feature hasn't been implemented as of Apache TinkerPop 3.4.2. It is a long standing open issue: TINKERPOP-1084. I think that if you want this functionality, you're going to have do a nested choose():
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().hasLabel('person').
......1> choose(values('age').is(lt(29)),
......2> constant('lt29'),
......3> choose(values('age').is(gt(29)),
......4> constant('gt29'),
......5> constant('29')))
==>29
==>lt29
==>gt29
==>gt29
Note that you aren't restricted to constant() as a result of these nested choose() operations. You can add any anonymous traversal you like there as in:
gremlin> g.V().hasLabel('person').
......1> choose(values('age').is(lt(29)),
......2> constant('lt29'),
......3> choose(values('age').is(gt(29)),
......4> math('_ - 29').by('age'),
......5> constant('29')))
==>29
==>lt29
==>3.0
==>6.0

Gremlin lower case / upper case

Based on the Modern Graph,
When I do a between search for a name, it seems to be case sensitive
gremlin> g.V().has("name", between("m", "mz")).values("name")
==>marko
gremlin> g.V().has("name", between("M", "Mz")).values("name")
gremlin>
I looked up but did not find a lower() or upper(), what I am trying to do is lower(x) == lower(y) so that the above becomes case in-sensitive.
You could or() the required conditions together:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.addV('person').property('name','Marvin')
==>v[13]
gremlin> g.addV('person').property('name','Marko')
==>v[15]
gremlin> g.V().or(has("name", between("Marko", "N")),has("name", between("marko", "n")))
==>v[1]
==>v[13]
==>v[15]
gremlin> g.V().or(has("name", between("Marko", "Markoz")),has("name", between("marko", "markoz")))
==>v[1]
==>v[15]
Just a warning - this approach works, but different graphs will treat this type of query differently. I don't know that all will optimize this type of query. If you're just experimenting on a small graph, then this approach might be fine, but you might not see the performance you want on a large graph depending on the traversal.

How to create a bidirectional edge between two vertices using gremlin?

What is the best way to create a bidirectional edge between two vertices using gremlin. Is there a direct command which adds the edge or should we add two edges like vertex X -> Vertex Y and vertex Y -> Vertex X?
You can add an edge between two vertices and then ignore the direction at query-time by using the both() step. This is how you typically address bidirectional edges in Gremlin.
Let's open the Gremlin Console and create a simple graph where Alice and Bob are friends:
\,,,/
(o o)
-----oOOo-(3)-oOOo-----
gremlin> graph = TinkerGraph.open()
gremlin> g = graph.traversal(standard())
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin>
==>null
gremlin> g.addV(label, 'user', 'name', 'Alice').as('alice').addV(label, 'user', 'name', 'Bob').as('bob').addE('friendWith').from('alice').to('bob')
==>e[4][0-friendWith->2]
This creates a graph with two vertices and one edge:
gremlin> g.V()
==>v[0]
==>v[2]
gremlin> g.E()
==>e[4][0-friendWith->2]
Notice how you cannot traverse from the Bob vertex to the Alice vertex in the outgoing direction, but you can traverse in the ingoing direction (first query yields no result).
gremlin> g.V().has('name', 'Bob').out('friendWith')
gremlin> g.V().has('name', 'Bob').in('friendWith')
==>v[0]
Or starting from Alice (second query yields no result), you get the opposite:
gremlin> g.V().has('name', 'Alice').out('friendWith')
==>v[2]
gremlin> g.V().has('name', 'Alice').in('friendWith')
However, you can traverse the graph in both directions with the both() step, and retrieve Alice's friend or Bob's friend.
gremlin> g.V().has('name', 'Alice').both('friendWith')
==>v[2]
gremlin> g.V().has('name', 'Bob').both('friendWith')
==>v[0]
This would also work on more complex graphs with more than two vertices and one friendship relationship. The both() step simply ignores the direction of the edges when attempting to traverse to adjacent vertices.

Resources