Using Gremlin, I can create a vertex in an Azure Cosmos DB graph by issuing
g.addV('the-label').property('id', 'the-id')
and subsequently find it using
g.V('the-label').has('id', 'the-id')
However, I haven't found a way to issue a query that will insert the node if it is missing, and just get the reference to it if it already exists. Is there a way?
My concrete use case is that I want to add an edge between two nodes, regardless of whether those nodes (or the edge, for that matter) exist already or not, in a single query. I tried this upsert approach, but apparently Cosmos DB does not support Groovy closures, so it won't work.
The "upsert pattern" is relatively well defined and accepted at this point. It is described here. If you want to extend that to also add an edge, that's possible too:
g.V().has('event','id','1').
fold().
coalesce(unfold(),
addV('event').property('id','1')).as('start').
coalesce(outE('link').has('id','3'),
coalesce(V().has('event','id','2'),
addV('event').property('id','2')).
addE('link').from('start').property('id','3'))
If that looks a bit complex you can definitely simplify with a Gremlin DSL (though I'm not sure that CosmosDB supports Gremlin bytecode at this point). Here's an example with even more complex upsert logic simplified by a DSL. It's discussed in this blog post in more detail.
UPDATE: As of TinkerPop 3.6.0, the fold()/coalesce()/unfold()
pattern has been largely replaced by the new steps of mergeV()
and mergeE()
which greatly simplify the Gremlin required to do an upsert-like operation.