0

Context

I am working with a very complex graph, but for the shake of making it easier to understand and give an answer, I have created the following abstraction/simplification of my graph:

A1 -owns-> B1 -approves-> C1
              -approves-> C2
              -approves-> C3

   -owns-> B2 -approves-> C1

   -owns-> B3 -approves-> C1
              -approves-> C3

A2 -owns-> B4 -approves-> C1
              -approves-> C2
              -approves-> C3

   -owns-> B5 -approves-> C1
              -approves-> C2

   -owns-> B6 -approves-> C1
              -approves-> C3

IMPORTANT: you will have to assume that A's, B's and C's (as well as the 'approves' edge have properties). Thanks to @Kelvin Lawrence I have recreate the graph with:

g.addV('A1').property('name','A1Name').property('code','A1Code').as('a1').
  addV('A2').property('name','A2Name').property('code','A2Code').as('a2').
  addV('B1').property('name','B1Name').property('code','B1Code').as('b1').
  addV('B2').property('name','B2Name').property('code','B2Code').as('b2').
  addV('B3').property('name','B3Name').property('code','B3Code').as('b3').
  addV('B4').property('name','B4Name').property('code','B4Code').as('b4').
  addV('B5').property('name','B5Name').property('code','B5Code').as('b5').
  addV('B6').property('name','B6Name').property('code','B6Code').as('b6').
  addV('C1').property('name','C1Name').property('code','C1Code').as('c1').
  addV('C2').property('name','C2Name').property('code','C2Code').as('c2').
  addV('C3').property('name','C3Name').property('code','C3Code').as('c3').
  addE('owns').from('a1').to('b1').
  addE('owns').from('a1').to('b2').
  addE('owns').from('a1').to('b3').
  addE('owns').from('a2').to('b4').
  addE('owns').from('a2').to('b5').
  addE('owns').from('a2').to('b6').
  addE('approves').property('type','00').from('b1').to('c1').
  addE('approves').property('type','01').from('b1').to('c2').
  addE('approves').property('type','02').from('b1').to('c3').
  addE('approves').property('type','03').from('b2').to('c1').
  addE('approves').property('type','04').from('b3').to('c1').
  addE('approves').property('type','00').from('b3').to('c3').
  addE('approves').property('type','01').from('b4').to('c1').
  addE('approves').property('type','02').from('b4').to('c2').
  addE('approves').property('type','03').from('b4').to('c3').
  addE('approves').property('type','04').from('b5').to('c1').
  addE('approves').property('type','00').from('b5').to('c2').
  addE('approves').property('type','01').from('b6').to('c1').
  addE('approves').property('type','02').from('b6').to('c3')

Problem / What I need

Taking as an input A1's id, I would like to retrieve the data as follows (explanation below):

[
 C1
 {
  properties,
  [
  {
   B1 { properties },
   approvedbyB1 { properties }
  },
  {
   B2 { properties },
   approvedbyB2 { properties }
  },
  {
   B3 { properties },
   approvedbyB3 { properties }
  }
  ]
 },
 C2
 {
  properties,
  [
  {
   B1 { properties },
   approvedbyB1 { properties }
  },
  {
   B2 { properties }
  },
  {
   B3 { properties },
  }
  ]
 },
 C3
 {
  properties,
  [
  {
   B1 { properties },
   approvedbyB1 { properties }
  },
  {
   B2 { properties }
  },
  {
   B3 { properties },
   approvedbyB3 { properties }
  }
  ]
 }
]

Essentially, it is a list of 'C' (with all of its properties) which contains a list of 'Bs' (with all of its properties and their respective approval if exists) owned by the given 'A'.

With 'A1' as an input the result, ideally, would look something like this:

[
  C1:[B1{B1approval}, B2{B2approval}, B3{B3approval}],
  C2:[B1{B1approval}, B2, B3],
  C3:[B1{B1approval}, B2, B3{B3approval}
]

But something like this would be acceptable too:

[
  C1:[B1{B1approval}, B2{B2approval}, B3{B3approval}],
  C2:[B1{B1approval}],
  C3:[B1{B1approval}, B3{B3approval}
]

Note: It is important for me to retrieve the whole object with all its properties, not only the id.


Conclusion / I have already tried

I am using CosmosDB implementation for Gremlin graph and I have tried using union, select, where and groupby steps but I haven't managed to retrieve the data in such way.

As I said before, it would also be acceptable if the JSON does not contain the 'Bs' without an approval, but ideally I would need that piece of information.

If you need further information to understand or to solve the problem in an specific way, please let me know.

Thanks in advance!

Maxinfamily
  • 13
  • 1
  • 4

1 Answers1

0

First of all I created the following steps to create the graph you described.

g.addV('A1').as('a1').
  addV('A2').as('a2').
  addV('B1').as('b1').
  addV('B2').as('b2').
  addV('B3').as('b3').
  addV('B4').as('b4').
  addV('B5').as('b5').
  addV('B6').as('b6').
  addV('C1').as('c1').
  addV('C2').as('c2').
  addV('C3').as('c3').
  addE('owns').from('a1').to('b1').
  addE('owns').from('a1').to('b2').
  addE('owns').from('a1').to('b3').
  addE('owns').from('a2').to('b4').
  addE('owns').from('a2').to('b5').
  addE('owns').from('a2').to('b6').
  addE('approves').from('b1').to('c1').
  addE('approves').from('b1').to('c2').
  addE('approves').from('b1').to('c3').
  addE('approves').from('b2').to('c1').
  addE('approves').from('b3').to('c1').
  addE('approves').from('b3').to('c3').
  addE('approves').from('b4').to('c1').
  addE('approves').from('b4').to('c2').
  addE('approves').from('b4').to('c3').
  addE('approves').from('b5').to('c1').
  addE('approves').from('b5').to('c2').
  addE('approves').from('b6').to('c1').
  addE('approves').from('b6').to('c3')      

Next we can follow the path from A1 to find the corresponding C1,C2,C3

gremlin> g.V().hasLabel('A1').out('owns').out('approves').dedup().label()
==>C1
==>C2
==>C3 

Having done that we can find the Bs

gremlin>  g.V().hasLabel('A1').as('a1').
......1>        out('owns').
......2>        out('approves').
......3>        dedup().
......4>        group().
......5>          by(label).
......6>          by(__.in('approves').where(__.in('owns').as('a1')).label().fold())

==>[C3:[B1,B3],C1:[B1,B2,B3],C2:[B1]]   

With these building blocks you should be able to generate the exact query you need. As there are no properties in your sample schema I was not able to show those.

Kelvin Lawrence
  • 14,674
  • 2
  • 16
  • 38
  • Thanks a lot Kevin! It helps but it is not quite what I need since I also need to retrieve Cs' properties, and as far as I know, the group step only allows you to create a key:value list in which the key can only be a single value. forgive me if I am wrong P.S: I have added more details and your graph recreation in the post, thanks again! – Maxinfamily Jul 05 '21 at 20:05
  • The key and or value can be another map. You can also nest `group` steps. – Kelvin Lawrence Jul 05 '21 at 20:08
  • With cosmosDB's implementation? For some reason there are particular ways to use steps/syntax that does not work in CosmosDB. Would you be able to provide me with a sample or a link with a sample? Thanks! – Maxinfamily Jul 05 '21 at 20:29
  • That I don't know I'm afraid. It's allowed by Gremlin/TinkerPop - not sure about specific implementation limitations with CosmosDB. – Kelvin Lawrence Jul 05 '21 at 20:40
  • Thanks again Kevin. I am looking for ways to implement it, and I will post the solution myself if none posts before I solve it. Anyway, thanks for the lead! – Maxinfamily Jul 05 '21 at 20:43