4

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.

dragos
  • 183
  • 1
  • 1
  • 13

1 Answers1

0

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]
stephen mallette
  • 45,298
  • 5
  • 67
  • 135
  • I'm happy to delete this answer if another is provided that demonstrates how this works. – stephen mallette Jun 12 '21 at 10:28
  • Thanks, Stephen, I know the limitation but I'm looking for a smart solution to counter this limitation. Like probably exporting the results of 1 query with all the data of `field1` for each node mapped to vertex id, then use this data somehow for the next set of queries to update the DB nodes with `field2`. This is a one time operation required on the DB. – dragos Jun 12 '21 at 15:51
  • that's what i suggested in the last sentence. get all your data to update in query then loop through it and update with additional queries. i think that's the only solution with CosmosDB. – stephen mallette Jun 13 '21 at 12:08
  • Can you provide a tested query for the 2 steps? – dragos Jun 14 '21 at 03:41
  • i've added an example, but i'm not able to test with cosmosdb. i've not know cosomosdb to have problems with this pattern. as you can see, there really isn't anything special to this approach. basically getting the data with one query in some way and then looping over it with a query per returned value to do the updates. – stephen mallette Jun 14 '21 at 10:32