Gremlin lower case / upper case - gremlin

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.

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

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.

Gremlin BFS enumeration including root

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]

How to replace an edge with Gremlin script

I want to look for a vertex, get an edge 'views', remove it, and replace with a new edge between the same vertices.
g.V('uuid','bf4dcbd24e9944319954dec5ad60c658')
.inE('views')
.sideEffect{g.addEdge(it.outV.next(),it.inV.next(),'likes')}
.sideEffect{g.removeEdge(it)}
This works, but is it the best way? Renaming the edge is an option?
You can use sideEffect as you did. That approach has the positive aspect of being straightforward and easy to understand. However, my personal preference for "production" Gremlin code is to use explicit Gremlin functions when they are available. In this case, I see the opportunity to use "link" and "step closures" (https://github.com/tinkerpop/gremlin/wiki/Step-Closures):
gremlin> g = TinkerGraphFactory.createTinkerGraph()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.E
==>e[10][4-created->5]
==>e[7][1-knows->2]
==>e[9][1-created->3]
==>e[8][1-knows->4]
==>e[11][4-created->3]
==>e[12][6-created->3]
gremlin> g.v(1).as('x').outE('knows').as('toRemove').inV.except('x').linkIn('swonk','x').sideEffect{v,m->g.removeEdge(m.toRemove)}
==>v[2]
==>v[4]
gremlin> g.E
==>e[1][1-swonk->4]
==>e[10][4-created->5]
==>e[0][1-swonk->2]
==>e[9][1-created->3]
==>e[11][4-created->3]
==>e[12][6-created->3]
In the above I "rename" all the "knows" edges for g.v(1) to "swonk".
fixed the first error before queston eddit.
Done...
g.V('uuid','bf4dcbd24e9944319954dec5ad60c658')
.inE('views')
.sideEffect{g.addEdge(it.outV.next(),it.inV.next(),'likes')}
the .next() fixed the script..

Resources