How to drop an edge in Gremlin? - 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()

Related

How to add multiple edges from one vertex in a single traversal

I have three user vertices. Tom and Mike follow Bob.
g.addV("user").property(single,"name", "bob")
g.addV("user").property(single,"name", "tom")
g.addV("user").property(single,"name", "mike")
g.V().hasLabel("user").has("name", "tom").as("tom").V().hasLabel("user").has("name", "bob").addE("follow").from("tom")
g.V().hasLabel("user").has("name", "mike").as("mike").V().hasLabel("user").has("name", "bob").addE("follow").from("mike")
I'd like to add an alert with edges to the users. There should be an edge from Bob to the alert, and the alert should have edges out to the users that follow Bob.
g.V()
.hasLabel("user")
.has("name", "bob")
.as("bob")
.in("follow")
.as("followers")
.addV("alert")
.as("alert")
.addE("alert")
.from("alert")
.to("followers")
.addE("alert")
.from("bob")
.to("alert")
What I end up with is two alert vertices. Bob has an edge to each of these new alert vertices, and the alerts have edges out to Tom and Mike (the followers).
I believe this is because when I select the followers, it branches (?) the traversal and starts creating the duplicates but this is not what I want. How do I construct this traversal to make the appropriate selections but only create a single alert vertex? What I'm trying to get is this:
bob
|
v
alert
| |
v v
mike tom
You are correct that the duplicates come from the fact that in('follow') produces two traversers and thus addV('alert') gets called multiple times. There are many way you might resolve this, but here is the approach that came immediately to mind for me:
gremlin> g.V().
......1> hasLabel("user").
......2> has("name", "bob").as("b").
......3> addV("alert").as('a').
......4> addE("alerted").from("b").
......5> select('b').
......6> in("follow").
......7> addE("alerted").from("a").iterate()
gremlin> g.V()
==>v[0]
==>v[2]
==>v[4]
==>v[8]
gremlin> g.V().elementMap()
==>[id:0,label:user,name:bob]
==>[id:2,label:user,name:tom]
==>[id:4,label:user,name:mike]
==>[id:8,label:alert]
gremlin> g.E().elementMap()
==>[id:6,label:follow,IN:[id:0,label:user],OUT:[id:2,label:user]]
==>[id:7,label:follow,IN:[id:0,label:user],OUT:[id:4,label:user]]
==>[id:9,label:alerted,IN:[id:8,label:alert],OUT:[id:0,label:user]]
==>[id:10,label:alerted,IN:[id:2,label:user],OUT:[id:8,label:alert]]
==>[id:11,label:alerted,IN:[id:4,label:user],OUT:[id:8,label:alert]]

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 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.

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