Search code examples
azure-cosmosdbgremlinazure-cosmosdb-gremlinapi

Azure Cosmos Graph nest edge vertex in a vertex property


I have two vertex:

1) Vertex 1: { id: 1, name: “john” }

2) Vertex 2: { id: 2, name: “mary” }

There is an edge from 1 to 2 named “children”.

Is it possible to return 2 nested in 1 using gremlin like this?

  { 
    id: 1, 
    name: “john”,
    children: { id: 2, name: “mary” }
  }

Thank you!

My solution with an amazing help of @noam621 ---------------------------------


g.V(1)
.union( valueMap(true),
        project('children').by( coalesce( out('children').valueMap(true).fold() , constant([]))),
        project('parents').by( coalesce( out('parents').valueMap(true).fold() , constant([])))
)
.unfold().group().by(keys).by(select(values))

It returns the following object:

{ 
    id: 1, 
    name: [ “john” ],
    children: [ { id: 2, name: [ “mary” ] } ],
    parents: []
}

.union with project are the key to merge all objects in one object. valueMap(true).fold() is fundamental to get all objects in the edge and coalesce helps with a default value if the edge doesn't return any vertex.

Due to some Azure Cosmos gremlin limitations is only possible to get values as array values. Thus I finalized the object formatting in my application code. It's ok for now.

Thank you!


Solution

  • You can do it by using the project step for both vertexes:

    g.V(1).project('id', 'name', 'children').
        by(id).
        by('name').
        by(out('children').
          project('id', 'name').by(id).
            by('name'))
    

    example: https://gremlify.com/3j


    query with valueMap:

    g.V(1).union(
        valueMap().
          with(WithOptions.tokens).by(unfold()),
        project('children').
          by(out('children').
            valueMap().
              with(WithOptions.tokens).by(unfold()))
      ).unfold().
      group().by(keys).
        by(select(values))
    

    if valueMap().with(WithOptions.tokens) not supported in Cosmos use valueMap(true) instead