How to replace deprecated addInE and addOutE steps with addE? - gremlin

I am completely new to Gremlin and have some really old code that is using addInE() and addOutE(). I understand that it is deprecated as of release 3.1.0 and - according to the javadocs - should be replaced with addE().
My problem is that I have very little knowledge of Gremlin in general and found almost no documentation for the addInE() and addOutE() steps.
In the reference documentation for version 3.0.0 there is exactly one example where it is used, but not explained.
Here is the example that is given:
gremlin> g.V(1).as('a').out('created').in('created').where(neq('a')).addOutE('co-developer','a','year',2009) //(1)
==>e[12][4-co-developer->1]
==>e[13][6-co-developer->1]
gremlin> g.withSideEffect('a',g.V(3,5).toList()).V(4).addInE('createdBy','a') //(2)
==>e[14][3-createdBy->4]
==>e[15][5-createdBy->4]
gremlin> g.V().as('a').out('created').as('b').select('a','b').addOutE('b','createdBy','a','acl','public') //(3)
==>e[16][3-createdBy->1]
==>e[17][5-createdBy->4]
==>e[18][3-createdBy->4]
==>e[19][3-createdBy->6]
gremlin> g.V(1).as('a').out('knows').addInE('livesNear','a','year',2009).inV().inE('livesNear').values('year') //(4)
==>2009
==>2009
My current interpretation of the first query
g.V(1).as('a').out('created').in('created').where(neq('a')) selects elements from the graph
addOutE('co-developer','a','year',2009) will add something to the selection
I would appreciate if someone could first elaborate on what is happening here and then point out how addInE() and addOutE() could be represented using addE().

This is a trip down memory lane!
Using one of the examples you found
gremlin> g.V(1).as('a').out('created').in('created').where(neq('a')).addOutE('co-developer','a','year',2009)
would, in current day Gremlin be written as
g.V(1).as('a').
out('created').
in('created').
where(neq('a')).
addE('co-developer').to('a').property('year',2009)
The way to read this is
Starting at the vertex with an ID of one.
Find all the vertices connected to V(1) by outgoing 'created' edges
Find all the people who also created the same thing
Don't include where you started (ie ignore yourself)
Add a new 'co-developer' edge to V(1) from the people found, with an edge property of the year.
When replacing addInE still use the addE step, but replace the to with a from. Note that an addE can also have both from and to used with it at the same time.

Related

How do I produce output even when there is no edge and when using select for projection

Can someone help me please with this simple query...Many thanks in advance...
I am using the following gremlin query and it works well giving me the original vertex (v) (with id-=12345), its edges (e) and the child vertex (id property). However, say if the original vertex 'v' (with id-12345) has no outgoing edges, the query returns nothing. I still want the properties of the original vertex ('v') even if it has no outgoing edges and a child. How can I do that?
g.V().has('id', '12345').as('v').
outE().as('e').
inV().
as('child_v').
select('v', 'e', 'child_v').
by(valueMap()).by(id).by(id)
There are a couple of things going on here but the major update you need to the traversal is to use a project() step instead of a select().
select() and project() steps are similar in that they both allow you to format the results of a traversal however they differ in (at least) one significant way. select() steps function by allowing you to access previously traversed and labeled elements (via as). project() steps allow you take the current traverser and branch it to manipulate the output moving forward.
In your original traversal, when there are no outgoing edges from original v so all the traversers are filtered out during the outE() step. Since there are no further traversers after the outE() step then remainder of the traversal has no input stream so there is no data to return. If you use a project() step after the original v you're able to return the original traverser as well as return the edges and incident vertex. This does lead to a slight complication when handling cases where no out edges exist. Gremlin does not handle null values, such as no out edges existing, you need to return some constant value for these statements using a coalesce statement.
Here is functioning version of this traversal:
g.V().hasId(3).
project('v', 'e', 'child_v').
by(valueMap()).
by(coalesce(outE().id(), constant(''))).
by(coalesce(out().id(), constant('')))
Currently you will get a lot of duplicate data, in the above query you will get the vertex properties E times. probably will be better to use project:
g.V('12345').project('v', 'children').
by(valueMap()).
by(outE().as('e').
inV().as('child').
select('e', 'child').by(id).fold())
example: https://gremlify.com/a1
You can get the original data format if you do something like this:
g.V('12345').as('v').
coalesce(
outE().as('e').
inV().
as('child_v')
select('v', 'e', 'child_v').
by(valueMap()).by(id).by(id),
project('v').by(valueMap())
)
example: https://gremlify.com/a2

Add edge if not exist using gremlin

I'm using cosmos graph db in azure.
Does anyone know if there is a way to add an edge between two vertex only if it doesn't exist (using gremlin graph query)?
I can do that when adding a vertex, but not with edges. I took the code to do so from here:
g.Inject(0).coalesce(__.V().has('id', 'idOne'), addV('User').property('id', 'idOne'))
Thanks!
It is possible to do with edges. The pattern is conceptually the same as vertices and centers around coalesce(). Using the "modern" TinkerPop toy graph to demonstrate:
gremlin> g.V().has('person','name','vadas').as('v').
V().has('software','name','ripple').
coalesce(__.inE('created').where(outV().as('v')),
addE('created').from('v').property('weight',0.5))
==>e[13][2-created->5]
Here we add an edge between "vadas" and "ripple" but only if it doesn't exist already. the key here is the check in the first argument to coalesce().
The performance of the accepted answer isn't great since it use inE(...), which is an expensive operation.
This query is what I use for my work in CosmosDB:
g.E(edgeId).
fold().
coalesce(
unfold(),
g.V(sourceId).
has('pk', sourcePk).
as('source').
V(destinationId).
has('pk', destinationPk).
addE(edgeLabel).
from('source').
property(T.id, edgeId)
)
This uses the id and partition keys of each vertex for cheap lookups.
I have been working on similar issues, trying to avoid duplication of vertices or edges. The first is a rough example of how I check to make sure I am not duplicating a vertex:
"g.V().has('word', 'name', '%s').fold()"
".coalesce(unfold(),"
"addV('word')"
".property('name', '%s')"
".property('pos', '%s')"
".property('pk', 'pk'))"
% (re.escape(category_),re.escape(category_), re.escape(pos_))
The second one is the way I can make sure that isn't a directional edge in either direction. I make use of two coalesce statements, one nested inside the other:
"x = g.V().has('word', 'name', '%s').next()\n"
"y = g.V().has('word', 'name', '%s').next()\n"
"g.V(y).bothE('distance').has('weight', %f).fold()"
".coalesce("
"unfold(),"
"g.addE('distance').from(x).to(y).property('weight', %f)"
")"
% (word_1, word_2, weight, weight)
So, if the edge exists y -> x, it skips producing another one. If y -> x doesn't exist, then it tests to see if x -> y exists. If not, then it goes to the final option of creating x -> y
Let me know if anyone here knows of a more concise solution. I am still very new to gremlin, and would love a cleaner answer. Though, this one appears to suffice.
When I implemented the previous solutions provided, when I ran my code twice, it produced an edge for each try, because it only tests one direction before creating a new edge.

create multiple edges having vertex id number 0 to 49

This can be a bit problem occuring for me as i am working for more time than needed . Can you tell me can i add an edge between two vertices and here i have 50 vertices and i cant find a way to add edge on it having vertex id 0 to 49 . Till now I have use
gremlin> (0..<50)each{g.addEdge(V[it],V[it+1]).next()}
No such property: V for class: groovysh_evaluate
gremlin> (0..<=49)each{g.addEdge(g.getVertex([NodeID]),g.getVertex([NodeID+1]),'abc')}
groovysh_parse: 2: unexpected token: = # line 2, column 6.
(0..<=49)each{g.addEdge(g.getVertex([NodeID]),g.getVertex([NodeID+1]),'abc')}
^
1 error
It looks like you just want to iterate through the vertices and add an edge from one vertex to the next until they are all connected. First, I'll create the 50 vertices:
gremlin> g.inject((0..<50).toArray()).as('i').addV('myid',select('i')).iterate()
Then I'll add the edges:
gremlin> (0..<49).each { def v = g.V().has('myid',(long) it).next(); v.addEdge('knows',g.V().has('myid',(long)it+1).next()) }
I cast to "long" in my example above as I was using a TinkerGraph. That cast may not be necessary for dynamo. Note that you can combine all of this into a single line with:
gremlin> g.addV().repeat(__.as('a').addV().as('b').
select(last,'a','b').
addE('.').from('a').to('b').
inV().as('a')).
times(49)
The above will create both the vertices and the edges at the same time in an iterative fashion. Note that "49" represents the number of edges you'd like to have.
You have spread this same question across multiple tags in StackOverflow including: here and here. In all cases you have lots of basic syntax errors and are calling methods that don't exist and referencing objects that don't exist. I suggest you focus on more of the basics of Java and Groovy before digging too deeply into dynamodb and TinkerPop. At a mimimum, start with the TinkerPop tutorials (like the one mentioned in the comment to your question) to get a better feel for the APIs and how the programmign syntax.

Gremlin-Server Add Vertex with Multiple Properties (Titan 1.0.0)

I'm creating a Titan graph (backed by Dynamodb); I'm using Titan 1.0.0 and running Gremlin-Server 3 (on TinkerPop3).
I'm trying to add a vertex to my graph with a label and multiple properties in a single line. I'm able to add a vertex with a label and a single property, and I can add multiple properties to a vertex after it has been created, but it seems that I can't do it all at once.
For testing I'm running commands in the gremlin shell, but the end use case is interacting with it via REST api (which is already working fine).
As a note, I'm rolling back after each of these transactions so I have a clean slate.
Here is how I'm initiating my session:
gremlin> graph = TitanFactory.open('conf/gremlin-server/dynamodb.properties')
==>standardtitangraph[com.amazon.titan.diskstorage.dynamodb.DynamoDBStoreManager:[127.0.0.1]]
gremlin> g = graph.traversal()
==>graphtraversalsource[standardtitangraph[com.amazon.titan.diskstorage.dynamodb.DynamoDBStoreManager:[127.0.0.1]], standard]
I can create a vertex with a label and a single property like this:
gremlin> graph.addVertex('date_of_birth').property('date_of_birth','1949-01-01')
==>vp[date_of_birth->1949-01-01]
gremlin> g.V().hasLabel('date_of_birth').has('date_of_birth','1949-01-01').valueMap()
==>[date_of_birth:[1949-01-01]]
I can also create a vertex and then append many properties afterward with a traversal starting at the vertex I just created:
gremlin> v1 = graph.addVertex('date_of_birth')
==>v[409608296]
gremlin> g.V(v1).property('date_of_birth','1949-01-01').property('year_of_birth',1949).property('date_of_birth','1949-01-01').property('day_of_birth',1).property('age',67).property('month_of_birth',1)
==>v[409608296]
gremlin> g.V(v1).valueMap()
==>[day_of_birth:[1], date_of_birth:[1949-01-01], month_of_birth:[1], age:[67], year_of_birth:[1949]]
This is all well and good, but I'm trying to avoid making 2 calls to achieve this result, so I'd like to create the vertex with all of these properties at once. Essentially, I want to be able to do something like the following, but it fails with more than 1 .property():
gremlin> graph.addVertex('date_of_birth').property('date_of_birth','1949-01-01').property('year_of_birth',1949).property('date_of_birth','1949-01-01').property('day_of_birth',1).property('age',67).property('month_of_birth',1)
No signature of method: com.thinkaurelius.titan.graphdb.relations.SimpleTitanProperty.property() is applicable for argument types: (java.lang.String, java.lang.String) values: [date_of_birth, 1949-01-01]
I've also tried using 1 .property() with multiple properties (along with all other syntax variations I could think of), but it only seems to catch the first one:
gremlin> graph.addVertex('date_of_birth').property('date_of_birth','1949-01-01','year_of_birth',1949,'date_of_birth','1949-01-01','day_of_birth',1,'age',67,'month_of_birth',1)
gremlin> g.V().hasLabel('date_of_birth').has('date_of_birth','1949-01-01').valueMap()
==>[date_of_birth:[1949-01-01]]
I've looked through all of the documentation I can get my hands on from all sources I can find and I can't find anything on this "all at once" method. Has anyone done this before or know how it could be done?
Thanks in advance!
As described in Chapter 3 Getting Started of the Titan docs, the GraphOfTheGodsFactory.java source code shows how to add a vertex with a label and multiple properties.
saturn = graph.addVertex(T.label, "titan", "name", "saturn", "age", 10000);
The method addVertex(Object... keyValues) ultimately comes from Graph interface defined by Apache TinkerPop. Titan 1.0.0 uses TinkerPop 3.0.1, and you can find more documentation on the addVertex step (and many other steps) in the TinkerPop docs.

ArangoDB Graph-Traversal: Exclude Edges

I'm executing a query similar to:
FOR v, e IN 1..10 ANY #start GRAPH #graph
FILTER e.someCondition
RETURN v
What I expected to happen was that if e.someCondition was false, then the edge in question wouldn't be traversed (and transitively, all other vertexes and edges reachable solely through e would never be visited).
However, it seems that what happens is that e is merely skipped and then traversal continues down that path.
So, how can I set boundaries on graph-traversal by edge-properties using AQL?
The query supports v, e and p, where p is the path it takes.
The ArangoDB documentation shows some examples.
I have used this to exclude specific nodes at specified depths in the path but you have to specify depth of nodes e.g. p.vertices[0].something != 'value').
Another thing you might want to look at is working with 'Custom Visitor' functions which are evaluated as the query traverses down a path.
This good blog post and this ArangoDB guide show some real world examples of it and it's well worth the read and effort to get a sample working. I've used these functions to summarise data in a path, aggregated by properties on the vertices in the path, but you can also use it to have custom paths followed.
This is worth the effort because it gives you huge flexibility over the computation it follows when traversing the graph. You can exclude branches, only include branches that meet specific requirements, or aggregate data about the paths it took.
I hope that helps.

Resources