GUID_33
GUID_33

Reputation: 800

gremlin - projecting to separate lists from single list with different where clauses

if I had this small graph:

addV('location').property('name','loc 1').property('active',true).property('size',2000).as('a')
addV('location').property('name','loc 2').property('active',true).property('size',1200).as('b')
addV('location').property('name','loc 3').property('active',true).property('size',1800).as('c')
addV('location').property('name','loc 4').property('active',true).property('size',2400).as('d')
addV('location').property('name','loc 5').property('active',true).property('size',2800).as('e')
addV('location').property('name','loc 6').property('active',true).property('size',4200).as('f')
addV('owner').property('name','john doe').as('o')

addV('building').property('name','building').property('active',true).as('building')
addE('on-property').from('a').to('building')

addE('owns').from('o').to('a')
addE('owns').from('o').to('b')
addE('owns').from('o').to('c')
addE('owns').from('o').to('d')
addE('owns').from('o').to('e')
addE('owns').from('o').to('f')

If I start with a base query like this:

//if 1 is the id of "john doe"
g.V(1).out('owns').has('active',true)

I want to do additional where clauses, but keep them separate so using or into a single list won't work.

The other consideration is that this is a small subset of a true graph so I don't really want to loop through them multiple times...i.e. I am thinking that a project would loop through the 1000+ locations for each projection, rather then doing a one time loop

 g.V(1)
      .project('sizeLimit','withBuildings')
         .by(out('my-locations').where(and(has('active',true),has('size',lt(2000)))))
         .by(out('my-locations').and(
               coalesce(
                  out('on-property').count(local),
                  constant(0)).is(gt(0))
               ,has('active',true)))

I tried to do the related portions of the query first rather then having to do the "out" in each of them like:

 g.V(1).out('my-locations')
        .has('active',true)
      .project('sizeLimit','withBuildings')
         .by(has('size',lt(2000)))
         .by(
               coalesce(
                  out('on-property').count(local),
                  constant(0)).is(gt(0))
               )

but the projection didn't take properly and ended up doing a single item per projection - even if I did a fold or unfold

So I am wondering if the first way with putting the out in the by rather then before is the only option or if I can aggregate or store the list and then do a where off that aggregate or somehow loop through and push to separate list?

I am using azure cosmos graph db.

The end look would hopefully be like this json:

"sizeLimit":[
  locationVertex,
  locationVertex,
  locationVertex
],
"withBuildings":[
  locationVertex,
  locationVertex
]

The "locationVertex" being the vertex that is returned by the filter for the set of the project.

Upvotes: 1

Views: 356

Answers (1)

stephen mallette
stephen mallette

Reputation: 46216

I'm not sure I fully follow your problem, but it sounds like you're mostly interested in keeping the out('owns') from the by() modulator because for each by() you add you will be re-traversing the same portion of the graph. You're quite close with your second traversal example (though you say it wasn't working quite right) - with some minor modifications it seemed to behave for me:

gremlin> g.V().has('name','john doe').
......1>   out('owns').has('active',true).
......2>   fold().
......3>   project('sizeLimit','withBuildings').
......4>     by(unfold().has('size',lt(2000)).fold()).
......5>     by(unfold().filter(out('on-property').count().is(gt(0))).fold())
==>[sizeLimit:[v[8],v[4]],withBuildings:[v[0]]]

I don't think you needed the coalesce() because count() will reduce the stream to zero when there are no outE() edges.

Upvotes: 2

Related Questions