I am going to update entire value of list property and set a new value for that in Titan 1.0, for single cardinality I can use vertex.property("single_property",new_value)
,and overwrite the whole value but for the cardinality of type List, the new value will be added to the property (it will not overwrite the whole value). Moreover, if I remove the property and add a new value, in the same transaction it seems that the whole operation will be ignored by Titan! Therefore, my question would be how can I update the whole value of list property in an appropriate way?
Regarding the solution provided by phani, the following code did not work for me, the insertion part worked, but the deletion part did not.
keywords = keywordExtractor.getKeywords(getId(nextVertex))
if (keywords.size() > 0) {
nextVertex.property(VertexProperty.Cardinality.single, "post_keyword", keywords.get(0));
keywords.remove(0);
for (String keyword : keywords) {
nextVertex.property(VertexProperty.Cardinality.list, "post_keyword", keyword);
}
}
nextVertex.graph().tx().commit();
Also the solution provide by Jason which is provided in the following did not work either. The problem was in the deletion part.
keywords = keywordExtractor.getKeywords(getId(nextVertex))
if (keywords.size() > 0) {
nextVertex.graph().traversal().V(nextVertex).properties("post_keyword").drop().iterate();
for (String keyword : keywords) {
nextVertex.property("post_keyword", keyword);
}
}
nextVertex.graph().tx().commit();
I also did investigate the following solution; did not work either.
keywords = keywordExtractor.getKeywords(getId(nextVertex))
if (keywords.size() > 0) {
Iterator<VertexProperty<Object>> iter = nextVertex.properties("post_keyword");
while(iter.hasNext()){
iter.next().remove();
}
for (String keyword : keywords) {
nextVertex.property("post_keyword", keyword);
}
}
nextVertex.graph().tx().commit();
Phani offered a solid answer that works great with TinkerGraph. The behavior in Titan is slightly different, so my suggestion is to drop()
the property first, then add new items to it afterwards.
gremlin> graph = TitanFactory.open('inmemory'); g = graph.traversal()
==>graphtraversalsource[standardtitangraph[inmemory:[127.0.0.1]], standard]
gremlin> mgmt = graph.openManagement()
==>com.thinkaurelius.titan.graphdb.database.management.ManagementSystem@71a06021
gremlin> name = mgmt.makePropertyKey('name').dataType(String.class).cardinality(Cardinality.LIST).make()
==>name
gremlin> mgmt.commit()
==>null
gremlin> v = g.addV('name','marko','name','marko a. rodriguez').next()
==>v[4312]
gremlin> g.V(v).properties('name').count()
==>2
gremlin> g.V(v).properties('name').drop().iterate()
gremlin> g.V(v).properties('name').count()
==>0
gremlin> v.property(list, 'name', 'm. a. rodriguez')
==>vp[name->m. a. rodriguez]
gremlin> g.V(v).properties('name').count()
==>1
Updated: Java code example
You would use Cardinality list
in the multi-property to add additional properties. If you want to remove existing values of a multi-property and add new list, you can do the following:
gremlin> v = g.addV('name','marko','name','marko a. rodriguez').next()
==>v[0]
gremlin> g.V(v).properties('name').count() //(1)
==>2
gremlin> v.property(list, 'name', 'm. a. rodriguez') //(2)
==>vp[name->m. a. rodriguez]
gremlin> g.V(v).properties('name').count()
==>3
gremlin> g.V(v).property('name','okram') //(3)
==>v[0]
gremlin> g.V(v).properties('name')
==>vp[name->okram]
gremlin> g.V(v).values('name') //(4)
==>okram
1 => you used addV with multiple properties with same name, hence the count is 2
2 => to add additional name property to an existing vertex with existing entries, you would mention the cardinality as list. This will append the new name to the list of available names
3 => to remove all existing name entries and add a new entry, you would simply omit the cardinality from the property
method
4 => Hence you can see only one name for the same vertex.
All the approaches provided which are presented at the main question can be used as a solution of updating the list/set cardinality property whole value. However, there is fact that should be taken into consideration to have a working solution.
In Titan 1.0 when you use backend indexing (such as ES or Solr) in a single transaction all addition and deletion will be investigated to find the unnecessary deleting operations. Somehow, deleting one property and adding the same property will be consolidated in Titan mutation class, and consequently the deletion operation will be ignored. For single cardinality such ignorance is not a problem because of overwriting the whole value by addition at the indexing backend, but for List/Set cardinality this will cause an inconsistency in backend indexing data.
Suppose there is one property deletion and same property addition for the List/Set cardinality property in the single titan transaction. After committing part, gremlin query shows that the overwriting whole property works, but if you check the indexing backend you will find out that the new property is added to the old property. From the Titan perspective, the remove property operation is consolidated to remove the unnecessary deletion! There are two solutions for this problem, either remove the consolidation
method from the Mutation
class in Titan (this will cause an unnecessary operation in single cardinality situation), or use multiple transaction for addition and deletion operations. I chose the second solution.