Why AddEdgeStep doesn't work after DropStep of edges in the same traversal using Gremlin? - gremlin

I have this code which essentially updates properties, removes all old IsOfType edges and adds new IsOfType edges (if I remove all the method/class abstraction and make it inline):
traversal = g.V("Entity:633471488:519").as("entity");
//update properties
traversal.property("text", "new text");
traversal.property("description", "new description");
//drop typeEdges
traversal.select("entity").outE("IsOfType").drop();
//even that causes the same issue(!): traversal.select("entity").outE("HasInner").drop();
System.out.println("traversal after type edges deletion: " +traversal);
//make new typeEdges
traversal.V("Entity:996942848:518").as("type-0").addE("IsOfType").from("entity").to("type-0");
System.out.println("traversal after type edges addition: " +traversal);
//storage
traversal.select("entity").forEachRemaining({})
Everything works (even the drop of existing IsOfType edges). But the creation of the new IsOfType edges doesn't seem to be resulting in new edges on the graph. If I comment out the drop, then creation works fine (!) It is as if the DropStep which is before the addEdgeStep is happening at the end. I even tried to drop other type of edge and it is causing the same issue (!). It might be that implicit transaction handling is deciding to commit when a drop() happens as it is with next(), iterate() and forEachRemaining() ?? If that is the case then drops and creations can't happen within the same transaction using Fluent API which renders it not very useful for real applications :(
Here is the state of the traversals after the deletion and after the additon of two IsOfType edges in my run (I tried both Java and Datastax Studio Console):
traversal after type edges deletion:
[
GraphStep(vertex,[Entity:633471488:519])#[entity],
AddPropertyStep({value=[Entity], key=[atClass]}),
AddPropertyStep({value=[FilmWithSuperCategories aaa], key=[text]}),
AddPropertyStep({value=[dffsdfsd f2313], key=[description]}),
SelectOneStep(entity)#[entity],
VertexStep(OUT,[IsOfType],edge),
DropStep
]
traversal after type edges addition:
[
GraphStep(vertex,[Entity:633471488:519])#[entity],
AddPropertyStep({value=[Entity], key=[atClass]}),
AddPropertyStep({value=[FilmWithSuperCategories aaa], key=[text]}),
AddPropertyStep({value=[dffsdfsd f2313], key=[description]}),
SelectOneStep(entity)#[entity],
VertexStep(OUT,[IsOfType],edge),
DropStep,
GraphStep(vertex,[Entity:996942848:518])#[type-0],
AddEdgeStep({~from=[[SelectOneStep(entity)]], ~to=[[SelectOneStep(type-0)]], label=[IsOfType]}),
GraphStep(vertex,[Entity:1489781376:516])#[type-1],
AddEdgeStep({~from=[[SelectOneStep(entity)]], ~to=[[SelectOneStep(type-1)]], label=[IsOfType]})
]
Edit
From what I read here (http://tinkerpop.apache.org/docs/current/reference/#drop-step)
The drop()-step (filter/sideEffect) is used to remove element and properties from the graph (i.e. remove). It is a filter step because the traversal yields no outgoing objects.
There are no objects being returned so it is not possible to do anything after a drop happens! so I am curious how I can do multiple drops/additions in a single transaction using DSE Graph Fluent API
Thanks!

You can wrap your drop in a sideEffect step, e.g.:
g.V(entity1).as("a").sideEffect(outE().filter(inV().is(entity2)).drop()).
V(entity2).addE("link").from("a")

Related

Need a query to retrieve complete graph

I am trying to retrieve all the node and properties details in parent-child hierarchy.
Nested within each other.
Since I am new with gremlin, graphDB I am having really tough time to get it done.
Please suggest a solution and if you could walk me through it, it will be great.
Following is my structure
And I am trying to keep the response as clean as possible.
I am using cosmosDB and Gremlin.
NET api for this.
I tried the following but it gave me response in key value,
g.V("some_id").repeat(out()).emit().tree().path()
g.V("some_id").emit().repeat(both().simplePath()).dedup()
please any kind of suggestion would be great.
I"m not sure what format you want your result, but use of path(), tree() or subgraph() would typically give you the graph structure. Since you are using CosmosDB, you're only options are path() and tree() as subgraph() does not appear to be supported.
Using this sample graph as a simple tree:
g.addV().property(id, '1').as('1').
addV().property(id, '2a').as('2a').
addV().property(id, '2b').as('2b').
addV().property(id, '3a').as('3a').
addV().property(id, '4a').as('4a').
addE('child').from('1').to('2a').
addE('child').from('1').to('2b').
addE('child').from('2a').to('3a').
addE('child').from('3a').to('4a')
you can see the effect of path() which basically gathers the contents of each step Gremlin took:
gremlin> g.V('1').repeat(out()).emit().path()
==>[v[1],v[2a]]
==>[v[1],v[2b]]
==>[v[1],v[2a],v[3a]]
==>[v[1],v[2a],v[3a],v[4a]]
Since I used out() we don't see the edges, but that is easily remedied by adding making a small adjustment to directly consume edges into the path history:
gremlin> g.V('1').repeat(outE().inV()).emit().path()
==>[v[1],e[0][1-child->2a],v[2a]]
==>[v[1],e[1][1-child->2b],v[2b]]
==>[v[1],e[0][1-child->2a],v[2a],e[2][2a-child->3a],v[3a]]
==>[v[1],e[0][1-child->2a],v[2a],e[2][2a-child->3a],v[3a],e[3][3a-child->4a],v[4a]]
Taken together with duplication removed on your application side you have a complete graph with path().
Replacing path() with tree() will essentially do that deduplication by maintaining the tree structure of the path history:
gremlin> g.V('1').repeat(out()).emit().tree()
==>[v[1]:[v[2b]:[],v[2a]:[v[3a]:[v[4a]:[]]]]]
gremlin> g.V('1').repeat(outE().inV()).emit().tree()
==>[v[1]:[e[0][1-child->2a]:[v[2a]:[e[2][2a-child->3a]:[v[3a]:[e[3][3a-child->4a]:[v[4a]:[]]]]]],e[1][1-child->2b]:[v[2b]:[]]]]
The Tree is just represented as a Map where each key represents a like a root and value is another Tree (i.e. the branches from it). It is perhaps better visualized this way:
gremlin> g.V('1').repeat(out()).emit().tree().unfold()
==>v[1]={v[2b]={}, v[2a]={v[3a]={v[4a]={}}}}
gremlin> g.V('1').repeat(out()).emit().tree().unfold().next().value
==>v[2b]={}
==>v[2a]={v[3a]={v[4a]={}}}
If neither of these structures are suitable and subgraph() is not available you can technically just capture and return the edges you traverse as the low level elements of your subgraph as described in this blog post.
Given the comments on this answer I also present the following option which used group():
gremlin> g.V('1').emit().
......1> repeat(outE().group('a').by(outV()).by(inV().fold()).inV()).cap('a').unfold()
==>v[1]=[v[2a], v[2b]]
==>v[3a]=[v[4a]]
==>v[2a]=[v[3a]]
It's not exactly a "tree" but if you know the root (in this case v[1]) you can find its key in the Map. The values are the children. You can then look up each of those keys in the Map to find if they have children and so on. For example, we can lookup v[2b] and find that it has no children while looking up [v2a] reveals a single child of [v3a]. Gremlin can be pretty flexible in getting answers if you can be sorta flexible in how you deal with the results.

Gremlin/AWS Neptune: Adding Edge w/ Properties

I currently have a series of two vertices in a parent/child relationship, two edges between them that I have no issue with.
The issue happens when I start attempting to add properties to the edge and I get an error message that gives only some help:
{
"requestId": "...",
"code": "InternalFailureException",
"detailedMessage": "null:to([[SelectOneStep(last,child)]])"
}
I can run the same pattern below on Gremlify, but I understand that is 3.5 as opposed to Neptune on 3.4.
Do I need to point back to the edge itself after adding in all the properties or am I supposed to specify to(select('child')) and then add all the properties while in scope (and then return back to child)?
Traversal Query:
g.V(13695)
.out("latest_parent_to").as("child")
.in("parent_to")
.addE("role")
.property(single,'name','some_role')
.to(
select("child")
).select("child")
Update: I made a few changes to try the other thought: addE > to(select(...)) > set properties. Different error this time:
{
"requestId": "77ee2b5b-8309-4226-b163-8b253450c721",
"code": "UnsupportedOperationException",
"detailedMessage": "Cardinality specification may not be used with Edge properties."
}
The reason for using the single cardinality is every property stored/returned as a set. This was to prevent accidentally appending when one should update.

Select multiple edges and vertexes in a gremlin query

I am creating a vertex with multiple edges but need a bit of help writing a query to retrieve the data.
Creation query
g.addV("referral")
.as("r")
.property("createdAt", Date.now())
.addE("prospect")
.from_("r")
.to(__.V(user.id))
.addE("opportunity")
.from_("r")
.to(__.V(second_user.id))
.addE("referredBy")
.from_("r")
.to(__.V(business.id))
.select("r")
.next()
I want to run a query that gets data from the first and second user. So far I have
g.V(business.id) //business
.in_("opportunity")
.as("referral")
.outV("referredBy")
.as("referrer")
.inV("prospect")
.as("prospect")
.select("referral", "referrer", "prospect")
.toList()
.next()
I'm getting an error when running this query. I basically want an array of a referral, referrer and prospect in one object that I can iterate through. Also any help on making my initial query better would be helpful.
Please let me know if this makes sense or if you need any other info. Any help would be appreciated.
The errors are because you are using outV when you should be using out. You only need to use inV and outV after outE and inE. So your query should be
g.V(business.id) //business
.in("opportunity")
.as("referral")
.out("referredBy")
.as("referrer")
.in("prospect")
.as("prospect")
.select("referral", "referrer", "prospect")
.toList()
Also you don't need next as you already have toList.
Lastly rather than use as and select I would look at the path step instead.
g.V(business.id) //business
.in("opportunity")
.out("referredBy")
.in("prospect")
.path()
.toList()

Want two Vertices off the same Edge in Gremlin

I have a graph like this
V('Producer')-E('RESPONSIBLE_PRODUCER)->V('Event')<-E('INSPECTED')-V('Engineer')
V('Event')<-E('ALIGNED_PRODUCER')-V('Producer')
That is, each 'Event' vertex has two incoming edges: one that terminates at an 'Engineer' vertex and another that terminates at a 'Producer' vertex. But the function of the Producer vertices are different depend on the edge label.
I want to get the originating Producer, the Event, Engineer and terminating Producer.
I have this gremlin code:
g.V().hasLabel('Producer').
as('responsible').
has('ProdId', 1234567).
out("RESPONSIBLE_PRODUCER").hasLabel('Event').as('event').
in("INSPECTED").hasLabel('Engineer').as('engineer').
select('responsible', 'event', 'engineer').
by(valueMap('name')).by(valueMap('name')).by(valueMap('name'))
That is, I chose a given Producer and get the Event and Engineer then return some details about each of those vertices.
I also want the Producer aligned to the Event in the same query but am not sure how to do this.
Any help is greatly appreciated.
You are looking for project:
g.V().has('Producer', 'ProdId', '1').as('r').
out("RESPONSIBLE_PRODUCER").hasLabel('Event').
project('responsible', 'event', 'engineer', 'aligned').
by(select('r').values('name')).
by(values('name')).
by(in('INSPECTED').values('name')).
by(in('ALIGNED_PRODUCER').values('name'))
You can see a "live" example of your problem here

Encounter warning when add edge in OrientDB

Here is my Code:
OrientVertex luca = graph.addVertex(null);
luca.setProperty("name", "John" + Integer.toString(i));
OrientVertex marko = graph.addVertex(null);
marko.setProperty("name", "Van Ness Ave." + Integer.toString(i + 1));
OrientEdge lucaKnowsMarko = graph.addEdge(null, luca, marko, "knows");
graph.commit();
Here is a snapshot of the same.
And then, I encountered this warning:
WARNING: The command 'create edge type 'knows' as subclass of 'E''
must be executed outside an active transaction: the transaction will
be committed and reopen right after it. To avoid this behavior execute
it outside a transaction (db=test)
Googling this problem, it seems that this question is relevant to the not-transactional and transactional databases operations.
You are working schema less, so OrientDB creates classes for you the first time you create vertexes/edges. In this case it was for the Edge class 'knows'. You can avoid this by creating classes at the beginning, or however, outside the scope of transaction. Try to execute this before your code, only once:
OrientGraphNoTx graph = new OrientGraphNoTx(url);
graph.createEdgeType("knows");
graph.shutdown();

Resources