2
votes

I would like to know if there is an easy way of adding edges to a remote graph from within a Java program. Currently, I have:

  • an instance of Gremlin-Server running (TP 3.0.0.M7) that allows connections to a Neo4j graph. gremlin-server.sh -i com.tinkerpop neo4j-gremlin 3.0.0.M7 was executed beforehand and server started with gremlin-server.sh conf/remote-objects.yaml
  • a Java application containing a Client object that connects to it.

As far as I know, the Java application can only communicate with the server by submitting Gremlin queries through the client.submitAsync() method (right?).

My problem is as follows: I'd to look up two vertices, and if they both exist, create an edge between them. If the Graph object itself were available in my Java application, this would have been just as easy as it is in a local Gremlin console. I'd simply write the Java equivalent to

gremlin> v = g.addVertex('name', 'Hank')
==>v[16]
gremlin> v2 = g.addVertex('name', 'Pete')
==>v[18]
gremlin> v.addEdge('knows', v2)
==>e[20][16-knows->18]
gremlin>

Adding an edge to a graph on a remote server is more difficult as I need to find the two vertices first, before adding the edge between them. My Java code to do so is as follows:

//The params object is a Map that binds `fromParam` and `toParam` to strings Hank and Pete, respectively
ResultSet r = client.submitAsync("g.V().has('name', fromParam)", params).get();
ResultSet r2 = client.submitAsync("g.V().has('name', toParam)", params).get();

This gives me back two DetachedVertex objects. A third query to add an edge between them is then

// outVertex and inVertex are the DetachedVertex objects added to params
ResultSet r3 = client.submitAsync("outVertex.attach(g).addEdge('knows', inVertex.attach(g))", params).get();

This seems to work, but it had me stumped for a couple of hours and seems to be an enormous trouble for such an elementary operation. My questions are therefore as follows:

  • Is there a Gremlin query that can unify these three queries? I.e. can I look up and add an edge between two disconnected vertices in a single query?
  • Or, is there a way for the Java program to reach the remote Graph object as if it were local?
1
What happens if you submit the entire task (both look-ups and the edge addition) as a single query: g.V('name', 'Hank').addEdge('knows', g.V('name', 'Pete'))?Faber
I meant: g.V('name', 'Hank').next().addEdge('knows', g.V('name', 'Pete').next())Faber
I never realized using g.V() twice in the same query is valid! I suppose adding some count() steps allows for checking for duplicates as well. Oh, and it should be g.V().has('name', 'Hank') instead of g.V('name', 'Hank'), but that's easy to fix :) Cheers for this. The answer to my second question is probably no, correct?rvw
In the gremlin console you can write g.V('name', 'Hank') instead of g.V().has('name', 'Hank'), dunno if this also works with your remote access approach. I assume that the former is more efficient if you've created an index on 'name'. The latter always iterates over all vertices, something you don't want to do. See gremlindocs: gremlindocs.com/#transform/vFaber
I'm working with Tinkerpop3, where that doesn't exist anymore. As far as I know, gremlindocs.com was written for TP2, and the only documentation on traversals in TP3 is found here.rvw

1 Answers

3
votes

Can't you submit a multi-line statement? I've never tried that, but I'd say it should work.

However, we're currently working on steps to make that easier, but for now you can also do this (in case you need a one-liner):

g.V().has('name', fromParam).as('from').map {
    g.V().has('name', toParam).tryNext().orElse(false)
}.is(neq, false).addInE('knows', 'from')

The following example show how this approach performs for existing and non-existing vertices:

gremlin> g = TinkerFactory.createModern()
==>tinkergraph[vertices:6 edges:6]
gremlin> g.V().has("name","marko").out("created")
==>v[3]
gremlin> g.V().has("name","marko").as("from").map {
             g.V().has("name", "riple").tryNext().orElse(false)
         }.is(neq, false).addInE("created", "from") // riple doesn't exist, hence no edge is being created
gremlin> g.V().has("name","marko").out("created")
==>v[3]
gremlin> g.V().has("name","marko").as("from").map {
             g.V().has("name", "ripple").tryNext().orElse(false)
         }.is(neq, false).addInE("created", "from") // ripple does exist, hence a new edge is being created
==>v[5]
gremlin> g.V().has("name","marko").out("created")
==>v[3]
==>v[5]