Question

I'm running Titan 0.3.2 with Cassandra as a data store. I'm also using rexpro-python for interacting with Titan over RexPro.

Issue & Question:

If I run this Python code:

>>> import rexpro
>>> conn = rexpro.RexProConnection('localhost', 8184, 'graph')
>>> conn.execute('g.addVertex(null, node_dict)', {'node_dict':{'my_dict':{}}})
{'_type': 'vertex', '_id': '2280164', '_properties': {'my_dict': {}}}
>>> conn.execute('g.commit()')

I can look up the resulting node in the Gremlin console:

gremlin> g.v(2280164).map
==>{my_dict={}}

And it looks like the my_dict map is created properly:

gremlin> g.v(2280164).my_dict.getClass()
==>class java.util.HashMap

However, I'm unable to update my_dict with a new key & value:

gremlin> g.v(2280164).my_dict['abc'] = 123
==>123
gremlin> g.commit()
==>null
gremlin> g.v(2280164).map
==>{my_dict={}}

If I first reset my_dict to a new object in the console, my attempt to add key abc works as expected:

gremlin> g.v(2280164).my_dict = [:]
gremlin> g.v(2280164).my_dict['abc'] = 123
==>123
gremlin> g.v(2280164).map
==>{my_dict={abc=123}}

My question: how can I update my_dict with a new KV pair on a vertex created via RexPro?


Attempted workarounds/solutions:

This same issue happens when the vertex is created with a non-parameterized version of the python script:

>>> conn.execute('g.addVertex([my_dict:[:]])')

Also, not sure if relevant for this issue, but it looks like the new map created in the console is a LinkedHashMap (whereas the python/rexpro code created a HashMap):

gremlin> g.v(2280164).my_dict.getClass()
==>class java.util.LinkedHashMap
Was it helpful?

Solution

Updating the dictionary/map that comes off a vertex property circumvents the database level since you are directly modifying the value on the heap. In other words, Titan does not know that you updated the map and therefore does not persist the change.

Always think of property values as immutable even though they might be mutable java objects because those mutations are invisible to the database.

This will work:

newdict = v.my_dict.clone()
newdict['hello']='other'
v.setProperty('my_dict',newdict)
graph.commit()
v.map

OTHER TIPS

I tried to recreate this entirely in the REPL and couldn't. I even explicitly created a java.util.HashMap and it seemed to work fine with Titan/Cassandra. I think LinkedHashMap is the default for groovy when you do [:].

gremlin> g = TitanFactory.open('bin/cassandra.local')
==>titangraph[cassandrathrift:127.0.0.1]
gremlin> g.addVertex()
==>v[4]
gremlin> g.v(4).my_dict = new java.util.HashMap()
gremlin> g.v(4).map
==>{my_dict={}}
gremlin> g.v(4).my_dict['abc'] = 123
==>123
gremlin> g.v(4).map
==>{my_dict={abc=123}}
gremlin> g.v(4).my_dict.getClass()
==>class java.util.HashMap
gremlin> g.commit()
==>null
gremlin> g.v(4).map
==>{my_dict={abc=123}}

What happens if you don't parameterize your RexPro request? In other words, do you get different results if you do:

>>> conn.execute('g.addVertex([my_dict:[:]])')

If that works that might be a workaround for you. I know the recommendation is to "parameterize requests" via RexPro but since this script is basically static, it will cache nicely in the scriptengine at not much additional cost per request.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top