CosmosDB: Gremlin Query to create a new property using existing property

Viewed 393

Each vertex has a structure:

{
    Id: 123,
    field1: 10
}

I want to add field2 to all the vertices such that field2 has its value equal to field1.

The challenge is that almost all the queries I found here as well as other places give syntax error in cosmos DB.

E.g.

g.V().has("field1").property("field2", values("field1")) 

This gives an error: Cannot create ValueField on non-primitive type GraphTraversal.

Please suggest a cosmos DB compatible query(multistep if required) to perform this operation on the DB. This is a one-time operation on the DB and will not be performed again.

1 Answers

As I've mentioned elsewhere, I'm not a CosmosDB expert, but I would venture to guess that what you're asking can't be done with CosmosDB. You definitely have the correct syntax in its most simple form, so the idea that a more complex form would somehow solve the problem seems unlikely. I imagine that property(String, Traversal) is simply unsupported at this time which means that an in-place update isn't not possible.

You could test the complex forms (e.g. select(Traversal,Traversal) for your own satisfaction if you like - for example, from this blog post that demonstrates how to update a vertex from map data:

gremlin> m = [name:'marko',age:29,country:'usa']
==>name=marko
==>age=29
==>country=usa
gremlin> g.withSideEffect('properties',m).
......1>   addV('person').as('vertex').
......2>   sideEffect(select('properties').
......3>              unfold().as('kv').
......4>              select('vertex').
......5>              property(select('kv').by(Column.keys), select('kv').by(Column.values)))
==>v[0]
gremlin> g.V().has('person','name','marko').elementMap()
==>[id:0,label:person,country:usa,name:marko,age:29]

Therefore your only recourse is to query the vertices you wish to update and then send additional traversals back to update the fields you want. Structurally, this suggestion is to simply retrieve the data in a Map form of the vertex identifier for the key and the value holding the data you wish to move and then simply use a for-loop over that returned list of maps to issue a query per id/value:

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> data = g.V().has('age')
==>v[1]
==>v[2]
==>v[4]
==>v[6]
gremlin> data = g.V().has('age').project('id','age').by(id).by('age').toList()
==>[id:1,age:29]
==>[id:2,age:27]
==>[id:4,age:32]
==>[id:6,age:35]
gremlin> data.each { g.V(it['id']).property('personAge',it['age']).iterate() };[]
gremlin> g.V().has('personAge').project('id','age').by(id).by('personAge')
==>[id:1,age:29]
==>[id:2,age:27]
==>[id:4,age:32]
==>[id:6,age:35]
Related