Search code examples
gremlin

Gremlin: how to overcome property null problem and write a query which updates all properties of a certain vertex?


I need to write a single Gremlin query that can set the new property values of a vertex. All the property names are known in advance (in this example: Type, Country, Status). Some of the property values can be null - and I don't know which ones in advance. The query should work for all cases. For example, let's say I currently have this query:

g.V(123).
property('Type',Type).
property('Country',Country).
property('Status',Status)

This query works fine if all the parameter (Type, Country, Status) values are non-null. If, say, Country is null, I get an error:

The AddPropertyStep does not have a provided value: AddPropertyStep({key=[Country]})

In such case I would need to use a different query to drop the property (by the way, is there a better way for dropping a property?):

g.V(123).
property('Type',Type).
property('Status',Status).
properties('Country').drop()

Is it possible to write a universal query that can handle both null and non-null values? I cannot use console or programming, just a single Gremlin query to be executed.

Thanks!


Solution

  • TinkerPop doesn't allow null values in properties (though you might find some graph databases allowing different semantics there, I suppose), so you should validate your data up front to ensure that it has some meaningful "empty value" as opposed to a null. If you can't do that for some reason, I guess you could use choose() step to "check for null":

    gremlin> g = TinkerFactory.createModern().traversal()
    ==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
    gremlin> g.V().has('person','name','marko').valueMap()
    ==>[name:[marko],age:[29]]
    gremlin> age = null
    gremlin> g.V().has('person','name','marko').choose(constant(age).count().is(0), properties('age').drop(),property('age',age))
    gremlin> g.V().has('person','name','marko').valueMap()
    ==>[name:[marko]]
    gremlin> age = 30
    ==>30
    gremlin> g.V().has('person','name','marko').choose(constant(age).count().is(0), properties('age').drop(),property('age',age))
    ==>v[1]
    gremlin> g.V().has('person','name','marko').valueMap()
    ==>[name:[marko],age:[30]]
    

    The check for "is null" is basically just: constant(age).count().is(0), which leans on the Gremlin's semantics for null values in a stream being empty and giving a count() of zero. It works, but it makes your Gremlin a little less readable. That might be a nice DSL step to add if you have to write that a lot.