Search code examples
azuregremlintinkerpop3azure-cosmosdb

Output vertice and adjacent vertices in same query with tinkerpop3


I'm new to gremlin and trying to find out how to get an article along with the author and attachments in the same result using Azure Cosmos DB with GraphSON.

My graph looks like this:

[User] <- (edge: author) - [Article] - (edge: attachments) -> [File1, File2]

I would like to fetch everything I need in the UI to show an article along with author and info about attachments in on request.

What I'm trying to fetch is something similar to this pseudo-code:

{
article: {...},
author: [{author1}],
attachment: [{file1}, {file2}]
}

My attempt so far:

g.V().hasLabel('article').as('article').out('author', 'attachments').as('author','attachments').select('article', 'author', 'attachments')

How can I write the query to get the distinct values?


Solution

  • When asking questions about Gremlin it is always helpful to provide some sample data in a form like this:

    g.addV('user').property('name','jim').as('jim').
      addV('user').property('name','alice').as('alice').
      addV('user').property('name','bill').as('bill').
      addV('article').property('title','Gremlin for Beginners').as('article').
      addV('file').property('file','/files/a.png').as('a').
      addV('file').property('file','/files/b.png').as('b').
      addE('authoredBy').from('article').to('jim').
      addE('authoredBy').from('article').to('alice').
      addE('authoredBy').from('article').to('bill').
      addE('attaches').from('article').to('a').
      addE('attaches').from('article').to('b').iterate()
    

    Note that I modified your edge label names to be more verb-like so that they distinguish themselves better from the noun-like vertex labels. It tends to read nicely with the direction of the edge, as in: article --authoredBy-> user

    Anyway, your problem is most easily solved with the project() step:

    gremlin> g.V().has('article','title','Gremlin for Beginners').
    ......1>   project('article','authors','attachments').
    ......2>     by().
    ......3>     by(out('authoredBy').fold()).
    ......4>     by(out('attaches').fold())
    ==>[article:v[6],authors:[v[0],v[2],v[4]],attachments:[v[10],v[8]]]
    

    In the above code, note the use of fold() within the by() steps - that will force the full iteration of the inner traversal and get it into a list. If you miss that step you will get just one result (i.e. the first).

    Going one step further, I added valueMap() and next'd the result so that you could better see the properties contained in the vertices above.

    gremlin> g.V().has('article','title','Gremlin for Beginners').
    ......1>   project('article','authors','attachments').
    ......2>     by(valueMap()).
    ......3>     by(out('authoredBy').valueMap().fold()).
    ......4>     by(out('attaches').valueMap().fold()).next()
    ==>article={title=[Gremlin for Beginners]}
    ==>authors=[{name=[jim]}, {name=[alice]}, {name=[bill]}]
    ==>attachments=[{file=[/files/b.png]}, {file=[/files/a.png]}]