2

I am using CosmosDB with GremlinAPI and I would like to perform simple calculation even though CosmosDB does not support the math step.

Imagine that I have vertex "Person" with the property Age that can have a edge "Owns" to another vertex "Pet" that also has the property Age. I would like to know if a given person has a cat that is younger than the person but not more than 10 years younger.

The query (I know this is just a part of it but this is where my problem is)

g.V().hasLabel("Person").has("Name", "Jonathan Q. Arbuckle").as("owner").values("age").inject(-10).sum().as("minAge").select("owner")

Returns an empty result but

g.V().hasLabel("Person").has("Name", "Jonathan Q. Arbuckle").as("owner").values("age").inject(-10).as("minAge").select("owner")

Returns the selected owner. It seems that if I do a sum() or a count() in the query, then I cannot do 'select("owner")' anymore.

I do not understand this behaviour. What should I do to be able to do a 'select("owner")' and be able to filter the Pets based on their age.

Is there some other way I can write this query?

Thank you in advance

1 Answers1

2

Steps like sum, count and max are known as reducing barrier steps. They cause what has happened earlier in the traversal to essentially be forgotten. One way to work around this is to use a project step. As I do not have your data I used the air-routes data set and used airport elevation as a substitute for age in your graph.

gremlin> g.V(3).
           project("elev","minelev","city").
             by("elev").
             by(values("elev").inject(-10).sum()).
             by("city")

==>[elev:542,minelev:532,city:Austin]

I wrote some notes about reducing barrier steps here: http://kelvinlawrence.net/book/PracticalGremlin.html#rbarriers

UPDATED

If you wanted to find airports with an elevation less than the starting airport by no more than 10 and avoiding the math step you can use this formulation.

g.V(3).as('a').
  project('min').by(values('elev').inject(-10).sum()).as('p').
  select('a').
  out().
  where(lt('a')).by('elev').
  where(gt('p')).by('elev').by('min') 
Kelvin Lawrence
  • 14,674
  • 2
  • 16
  • 38
  • 1
    Thank you for your answer. I would like to filter the persons/airport based on the values from the projection. In the air-routes example I would like to see if a given airport is connected to another airport with an elevation lower than the original airport but not more than 10 meters lower. Can you give me an example of a query like that? – Nils Hedström Jun 07 '20 at 16:12