Kevin Andres
Kevin Andres

Reputation: 81

Getting properties of a vertex along with the properties of its child vertices [Gremlin]

I’m using Gremlin for querying a Graph DB and I’m having trouble figuring out how to retrieve all properties of a specific vertex along with all properties of specific child vertices. I know valueMap() is generally the operation to use to expose properties of nodes, but I'm not sure I am using it correctly.

Here is a visual representation of the Graph that I am working with. In this graph there are author nodes, which can be related to multiple book nodes connected by a wrote edge. And a book node can be connected to multiple chapter nodes by a hasChapter edge. A book node has a title and year as additional properties, while a chapter node has a name and a length as additional properties:

enter image description here

Here is the data that produces the above graph:

g.addV('author').property(id, 'author1').as('a1').
  addV('book').
     property(id,'book1').
     property('title', 'Book 1').
     property('year', '1999').
     as('b1').
  addV('book').
     property(id,'book2').
     property('title', 'Book 2').
     property('year', '2000').
     as('b2').
  addV('book').
     property(id,'book3').
     property('title', 'Book 3').
     property('year', '2002').
     as('b3').
  addE('wrote').from('a1').to('b1').
  addE('wrote').from('a1').to('b2').
  addE('wrote').from('a1').to('b3').
  addV('chapter').
     property(id,'b1chapter1').
     property('name', 'The Start').
     property('length', '350').
     as('b1c1').
  addV('chapter').
     property(id,'b1chapter2').
     property('name', 'Trees').
     property('length', '500').
     as('b1c2').
 addV('chapter').
     property(id,'b2chapter1').
     property('name', 'Chapter 1').
     property('length', '425').
     as('b2c1').
 addV('chapter').
     property(id,'b2chapter2').
     property('name', 'Chapter 2').
     property('length', '650').
     as('b2c2').
 addV('chapter').
     property(id,'b2chapter3').
     property('name', 'Chapter 3').
     property('length', '505').
     as('b2c3').
 addE('hasChapter').from('b1').to('b1c1').
 addE('hasChapter').from('b1').to('b1c2').
 addE('hasChapter').from('b2').to('b2c1').
 addE('hasChapter').from('b2').to('b2c2').
 addE('hasChapter').from('b2').to('b2c3').
 iterate()

I would like to form a query that is able to return the properties of all books that are written by author1, along with all properties of each book’s chapters, ideally sorted by date (ascending). I'm wondering if it's possible to make a query that would return the results in the following fashion (or something similar enough that I can parse through on the client side):

 1 {'year': ['1999'], 'title': ['Book 1'], 'chapters': [{'name': ['The Start'], 'length': ['350']}, {'name': ['Trees'], 'length': ['500']}]}
 2 {'year': ['2000'], 'title': ['Book 2'], 'chapters': [{'name': ['Chapter 1'], 'length': ['425']}, {'name': ['Chapter 2'], 'length': ['650']}, {'name': ['Chapter 3'], 'length': ['505']}]}
 3 {'year': ['2002'], 'title': ['Book 3'], 'chapters': []}

So far, I have attempted a few variations of this query with no luck:

g.V('author1').as('writer')
  .out('wrote').as('written')
  .order().by('year', asc)
  .out('hasChapter').as('chapter')
  .project('written', 'chapter')
  .by(valueMap())

which returns:

1   {'written': {'name': ['The Start'], 'length': ['350']}, 'chapter': {'name': ['The Start'], 'length': ['350']}}
2   {'written': {'name': ['Trees'], 'length': ['500']}, 'chapter': {'name': ['Trees'], 'length': ['500']}}
3   {'written': {'name': ['Chapter 1'], 'length': ['425']}, 'chapter': {'name': ['Chapter 1'], 'length': ['425']}}
4   {'written': {'name': ['Chapter 2'], 'length': ['650']}, 'chapter': {'name': ['Chapter 2'], 'length': ['650']}}
5   {'written': {'name': ['Chapter 3'], 'length': ['505']}, 'chapter': {'name': ['Chapter 3'], 'length': ['505']}}

The above query only returns the chapter properties for all books with chapters, whereas I'm looking for a query that will give me all book properties (regardless of whether the book has chapters) and all chapter properties of each book. Anyone have any advice on the use of valueMap() across multiple levels of traversal. Ideally would like to avoid multiple queries to the Graph DB, but open to solutions that involve doing so.

Upvotes: 1

Views: 276

Answers (1)

PrashantUpadhyay
PrashantUpadhyay

Reputation: 877

This below query gives the result exactly as you needed. I think the key is projecting the values inside the by modulator.

gremlin> g.V('author1').
......1>   out('wrote').
......2>   order().by('year', asc).
......3>   project('year', 'title', 'chapters').
......4>     by('year').
......5>     by('title').
......6>     by(out('hasChapter').valueMap().fold())
==>[year:1999,title:Book 1,chapters:[[name:[Trees],length:[500]],[name:[The Start],length:[350]]]]
==>[year:2000,title:Book 2,chapters:[[name:[Chapter 1],length:[425]],[name:[Chapter 2],length:[650]],[name:[Chapter 3],length:[505]]]]
==>[year:2002,title:Book 3,chapters:[]]

Upvotes: 1

Related Questions