Proper way to update Edges in Bulbs (neo4j or titan)

1.2k views Asked by At

I'm experimenting with Bulbs to interface with a graph database. ( Production will use Titan, locally Neo4j seems best for experimenting ).

I can't wrap my head around this concept...

Bulbs shows how to create new Vertices...

>>> james = g.vertices.create(name="James")
>>> julie = g.vertices.create(name="Julie")
>>> g.edges.create(james, "knows", julie)

Digging into the docs, I can replace that with a "get or create" as well :

>>> james = g.vertices.get_or_create('name',"James",{'name':'james')

What I can't figure out, is how to get an existing Edge. My attempts so far have ended up with recreating dozens of "james knows julie" relationships, instead of accessing the existing one to update.

Can someone point me in the right direction?

1

There are 1 answers

2
espeed On BEST ANSWER

You can add/update an edge's properties, but with graph databases, you cannot update the attributes that make it an edge, i.e. you cannot update its incoming and outgoing vertex IDs or label. Instead, you delete the edge and add a new one.

Here are the different ways of getting and edge and updating its properties..

You can get an edge by its ID:

>>> from bulbs.rexster import Graph
>>> g = Graph()
>>> james = g.vertices.create(name="James")
>>> julie = g.vertices.create(name="Julie")
>>> edge = g.edges.create(james, "knows", julie)
>>> edge2 = g.edges.get(edge.eid)       # get the edge again
>>> assert edge == edge2
>>> edge2.someprop = "somevalue"
>>> edge2.save()

You can look up an edge by its properties if it has any and they are indexed:

# will return an iterator or None edges (may return more than one)
>>> edges = g.edges.index.lookup(someprop="somevalue") 
>>> edge = edges.next()
>>> edge.someprop = "newvalue"
>>> edge.save()

# will return 1 or None edges (or an error if more than 1 edge found)
>>> edge = g.edges.index.get_unique(someprop="somevalue") 
>>> edge.someprop = "newvalue"
>>> edge.save()

You can also get an edge using Gremlin by traversing its vertices:

>>> from bulbs.rexster import Graph
>>> g = Graph()
>>> script = "g.V('name',name1).outE(label).as('e').inV.has('name',name2).back('e')"
>>> params = dict(name1="James", label="knows", name2="Julie")
>>> edges = g.gremlin.query(script, params)
>>> edge = edges.next()
>>> edge.someprop = "newvalue"
>>> edge.save()

See the Gremlin Backtrack Pattern...

But the most efficient way to update an edge when you don't know its ID is to update the edge via the Gremlin script that looks it up (this way you only have one round trip to the server, not two):

>>> from bulbs.rexster import Graph
>>> g = Graph()
>>> script = "g.V('name',name1).outE(label).as('e').inV.has('name',name2).back('e').sideEffect{it.someprop = someprop}"
>>> params = dict(name1="James", label="knows", name2="Julie", someprop="somevalue")
>>> edges = g.gremlin.query(script, params)
>>> edge = edges.next()
>>> edge.someprop
'somevalue'

See https://github.com/tinkerpop/gremlin/wiki/Updating-a-Graph

And for readability, rather than writing Gremlin one liners in the Python REPL, I would put my Gremlin scripts in a gremlin.groovy file, as shown here:

http://bulbflow.com/docs/api/bulbs/groovy/

Here is a real-life example of using Gremlin to get or create an edge:

https://github.com/espeed/lightbulb/blob/master/lightbulb/gremlin.groovy#L88

And a detailed explanation of the code is here:

Is there a equivalent to commit in bulbs framework for neo4j