Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I update a specific edge property using Gremlin/Titan/TinkerPop3?

The goal

I have a simple enough task to accomplish: Set the weight of a specific edge property. Take this scenario as an example:

Example Graph Structure

What I would like to do is update the value of weight.

Additional Requirements

  • If the edge does not exist, it should be created.
  • There may only exist at most one edge of the same type between the two nodes (i.e., there can't be multiple "votes_for" edges of type "eat" between Joey and Pizza.
  • The task should be solved using the Java API of Titan (which includes Gremlin as part of TinkerPop 3).

What I know

I have the following information:

  • The Vertex labeled "user"
  • The edge label votes_for
  • The value of the edge property type (in this case, "eat")
  • The value of the property name of the vertex labeled "meal" (in this case "pizza"), and hence also its Vertex.

What I thought of

I figured I would need to do something like the following:

  1. Start at the Joey vertex
  2. Find all outgoing edges (which should be at most 1) labeled votes_for having type "eat" and an outgoing vertex labeled "meal" having name "pizza".
  3. Update the weight value of the edge.

This is what I've messed around with in code:

//vertex is Joey in this case
g.V(vertex.id())
    .outE("votes_for")
    .has("type", "eat")
    //... how do I filter by .outV so that I can check for "pizza"?
    .property(Cardinality.single, "weight", 0.99);
    //... what do I do when the edge doesn't exist?

As commented in code there are still issues. Would explicitly specifying a Titan schema help? Are there any helper/utility methods I don't know of? Would it make more sense to have several vote_for labels instead of one label + type property, like vote_for_eat?

Thanks for any help!

like image 524
Double M Avatar asked Nov 22 '16 16:11

Double M


People also ask

How do you make an edge in Gremlins?

Create an edge To create a new edge between two vertices, use the addEdge(v1, v2, label) method. The edge will be created with the label specified. In the example below two vertices are created and assigned to a variable (Gremlin is based on Groovy), then an edge is created between them.

How do you add a vertex in Gremlin?

In Gremlin nodes are referred to as “Vertexes”. To add a node/vertex to the graph, you simply use the command addV() on your graph traversal source. For consistency, most people use “g” as their default graph traversal source.

What is Gremlin Groovy?

Gremlin Groovy works by using the metaprogramming facilities provided by Groovy. Groovy is used to compile Gremlin syntax down to raw Java Pipes.


1 Answers

You are on the right track. Check out the vertex steps documentation.

Label the edge, then traverse from the edge to the vertex to check, then jump back to the edge to update the property.

g.V(vertex.id()).
  outE("votes_for").has("type", "eat").as("e").
  inV().has("name", "pizza").
  select("e").property("weight", 0.99d).
  iterate()

Full Gremlin console session:

gremlin> Titan.version()
==>1.0.0
gremlin> Gremlin.version()
==>3.0.1-incubating
gremlin> graph = TitanFactory.open('inmemory'); g = graph.traversal()
==>graphtraversalsource[standardtitangraph[inmemory:[127.0.0.1]], standard]
gremlin> vertex = graph.addVertex(T.label, 'user', 'given_name', 'Joey', 'family_name', 'Tribbiani')
==>v[4200]
gremlin> pizza = graph.addVertex(T.label, 'meal', 'name', 'pizza')
==>v[4104]
gremlin> votes = vertex.addEdge('votes_for', pizza, 'type', 'eat', 'weight', 0.8d)
==>e[1zh-38o-4r9-360][4200-votes_for->4104]
gremlin> g.E(votes).valueMap(true)
==>[label:votes_for, weight:0.8, id:2rx-38o-4r9-360, type:eat]
gremlin> g.V(vertex.id()).outE('votes_for').has('type','eat').as('e').inV().has('name','pizza').select('e').property('weight', 0.99d).iterate(); g.E(votes).valueMap(true)
==>[label:votes_for, weight:0.99, id:2rx-38o-4r9-360, type:eat]

Would explicitly specifying a Titan schema help?

If you wanted to start from the Joey node without having a reference to the vertex or its id, this would be a good use case for a Titan composite index. The traversal would start with:

g.V().has("given_name", "Joey")

Are there any helper/utility methods I don't know of?

In addition to the TinkerPop reference documentation, there are several tutorials that you can read through:

  1. Getting Started
  2. The Gremlin Console
  3. Recipes

Would it make more sense to have several vote_for labels instead of one label + type property, like vote_for_eat?

Depends on what your graph model or query patterns are, but more granular labels like vote_for_eat can work out fine. You can pass multiple edge labels on the traversal step:

g.V(vertex.id()).outE('vote_for_eat', 'vote_for_play', 'vote_for_sleep')

Update

There may only exist at most one edge of the same type between the two nodes

You can use the Titan schema to help with this, specifically define an edge label with multiplicity ONE2ONE. An exception will be thrown if you create more than one votes_for_eat between Joey and pizza.

like image 140
Jason Plurad Avatar answered Oct 07 '22 22:10

Jason Plurad