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

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.

Related

Gremlin - if multiple vertices return multiple values each, how to limit the result to one per vertex

Essentially, I'm trying to modify the following piece of Gremlin code such that instead of operating on a single vertex at a time - signified by g.V(1), it will work with multiple vertices at once (e.g. changing to g.V()), while still only limiting the number of returned results per vertex to one (see limit(1)).
g.V(1).repeat(out().simplePath()).until(has('color', 'red')).path().limit(1)
The above query will compute the shortest path from a given vertex to the closest vertex which has property(color)==red.
However, I want to compute the shortest path for multiple vertices passed in at the same time, while still only returning a single path per vertex.
I'm having difficulty modifying this without returning multiple paths for the same vertex however.
Deduplicating the result by the start vertex should give you the expected result.
g.V().as('a').
repeat(out().simplePath()).
until(has('color', 'red')).
dedup('a').
path()
Example using the modern toy graph:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().
......1> repeat(out().simplePath()).
......2> until(hasLabel('software')).
......3> path()
==>[v[1],v[3]]
==>[v[1],v[4],v[5]]
==>[v[1],v[4],v[3]]
==>[v[4],v[5]]
==>[v[4],v[3]]
==>[v[6],v[3]]
gremlin> g.V().as('a').
......1> repeat(out().simplePath()).
......2> until(hasLabel('software')).
......3> dedup('a').path()
==>[v[1],v[3]]
==>[v[4],v[5]]
==>[v[6],v[3]]

Gremlin: how to traverse backwards across the same edge

I have a simple graph with two vertices, having ids 'a' and 'b'.
I have assigned an edge from 'a' to 'b' with label = 'foo'
gremlin> g.V()
==>v[b]
==>v[a]
gremlin> g.E()
==>e[04b4b9fd-2f20-751d-5673-5aa9d7ce0285][a-foo->b]
My question: how do I traverse backwards along the same edge? For example, if a query traverses to an outbound vertex, how can that query then traverse back across the same edge to the inbound vertex?
My query is shown below:
g.E('04b4b9fd-2f20-751d-5673-5aa9d7ce0285').outV().as('outV')...[want to get the inV for the same edge, here]
There's a lot of different ways to do this. Here's a few that will hopefully inspire you to your answer. You probably shouldn't count on the order in which the vertices are returned in the following case, but you could do bothV():
gremlin> g.E(11).bothV()
==>v[4]
==>v[3]
To force order you could do a union():
gremlin> g.E(11).union(inV(),outV())
==>v[3]
==>v[4]
You could always project() your results:
gremlin> g.E(11).project('in','out').by(inV()).by(outV())
==>[in:v[3],out:v[4]]
If you need to do something with the outV() first and then come back to the edge after that to then traverse on inV() you could label the E() step with as():
gremlin> g.E(11).as('e').outV().hasLabel('person').select('e').inV()
==>v[3]
Hopefully, those examples help.

Gremlin query to find k distance vertices

I was trying to run a gremlin query to find k distance vertices from a given vertex v and omit directly connected vertices to v.
I am using Gremlin 3.2.6.
So, something like this, for a k-distance(friend of friend) isn't working properly
g.V(v).both().as(“x”).repeat(both()).times(k).where(neq("x")).dedup()
The above should omit the vertices in "x" but it is not.
My graph is directed and there may be edges in both directions between a pair of vertices.
Also, how do I make this general for given distances less than some k using loops(having a hard time with it) and is there some way to print the distance along with the vertex list. Thanks.
x should actually be an aggregation of all adjacent vertices, not just a reference to the adjacent vertex on the current path.
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V(1).both().aggregate("x").
repeat(both().dedup()).
times(5).
emit().
where(without("x"))
==>v[1]
==>v[6]
==>v[5]
And if you also want to exclude the start vertex, just add it to the collection:
gremlin> g.V(1).store("x").
both().aggregate("x").
repeat(both().dedup()).
times(5).
emit().
where(without("x"))
==>v[6]
==>v[5]

Finding out which Vertex and edges were traversed

I have the following Graph
If I write a Query g.V('A').Out(), how can I get that the values of the Edges which were traversed and the vertex which were encounterned in the traveral ?
You would need to tell Gremlin to not skip the edges. g.V().out() is shorthand for g.V().outE().inV(). In this case, you can interact with the value of the edges as you've explicitly told Gremlin to traverse them. I'll demonstrate with a few examples using the "modern" toy graph:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
To start, you might want to filter on a particular edge property and then traverse to adjacent vertices:
gremlin> g.V().outE().has('weight',gt(0.5)).inV()
==>v[4]
==>v[5]
You mentioned in your question that you might want to see the values of edges and the vertices you encountered. One way would be to use path():
gremlin> g.V().outE().has('weight',gt(0.5)).inV().path()
==>[v[1],e[8][1-knows->4],v[4]]
==>[v[4],e[10][4-created->5],v[5]]
You might also get more explicit to get specific properties from the edge:
gremlin> g.V().outE().has('weight',gt(0.5)).inV().path().by().by('weight')
==>[v[1],1.0,v[4]]
==>[v[4],1.0,v[5]]

How to remove mutiple edges in gremlin query

I created a edge called "created" between User vertex and Event vertex
user1(8312) ---created---> event1(1234)
user1(8312) ---created---> event2(4567)
user1(8312) ---created---> event3(7890)
I can delete one edge at a time,but if I want to delete mutiple edges have to loop though and hit multple db calls.Is there any way to delete mutiple edges at once.
If you want to drop edges between multiple vertices then you could do something like this:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V(1).outE()
==>e[9][1-created->3]
==>e[7][1-knows->2]
==>e[8][1-knows->4]
gremlin> g.V(1).outE().where(inV().hasId(within(2,3))).drop()
gremlin> g.V(1).outE()
==>e[8][1-knows->4]
You can read more about this in Gremlin Recipes.
I am not sure how you remove the edges, but if you simply want to remove all outgoing created edges from the vertex with the ID 8312, then this should work:
g.V(8312).outE('created').drop().iterate()

Resources