mrchangamire
mrchangamire

Reputation: 15

Gremlin query traversal in within() clause

I have the following minimal Gremlin graph illustrated below

Sample graph

This graph can be built with the following Gremlin:-

g.addV('type').property(id, 'discipline').addV('type').property(id, 'functionalClass').addV('type').property(id, 'class1').addV('type').property(id, 'class2').addV('equipment').property(id, 'pump').addV('deployment').property(id, 'deployment1').addV('measure').property(id, 'measurement1').addV('measure').property(id, 'measurement2')
g.V('discipline').addE('hasChild').to(g.V('functionalClass'))
g.V('functionalClass').addE('hasChild').to(g.V('class1'))
g.V('functionalClass').addE('hasChild').to(g.V('class2'))
g.V('pump').addE('hasClass').to(g.V('class1'))
g.V('pump').addE('hasDeployment').to(g.V('deployment1'))
g.V('functionalClass').addE('measurement').to(g.V('measurement2'))
g.V('functionalClass').addE('summaryMeasurement').to(g.V('measurement2'))
g.V('class1').addE('measurement').to(g.V('measurement1'))
g.V('class2').addE('measurement').to(g.V('measurement1'))
g.V('deployment1').addE('produces').to(g.V('measurement1'))
g.V('deployment1').addE('produces').to(g.V('measurement2'))

The query I am working with should get deployments and related measurements for the given pump. Measurements can be of type measurement or summaryMeasurement, defined by the inbound edge from the class/functionalClass vertex.

I have the following query which is just about there - to get measurements

g.V('pump').as('e').out('hasClass').as('c')
 .select('e').out('hasDeployment').as('d')
 .out('produces').as('m')
 .in('measurement').where(eq('c'))
 .select('d', 'm')

And the following to get summaryMeasurements

g.V('pump').as('e').out('hasClass').as('c')
 .select('e').out('hasDeployment').as('d')
 .out('produces').as('m')
 .in('summary_measurement').where(eq('c'))
 .select('d', 'm')

The issue is that this will only return measurements associated with the class to which the pump is directly related (measurement1 in the sample graph), whereas I would like to to get measurements associated with parents and grandparents of the class the pump is related to (measurement1 AND measurement2 in the sample graph).

I know I can get the parents of the class1 with the query

g.V('class1').union(__.id(), repeat(__.in('hasChild')).emit().id())

I have tried the following query unsuccessfully

g.V('pump').as('e').out('hasClass').as('c')
.select('e').out('hasDeployment').as('d')
.out('produces').as('m')
.in('measurement')
.where(hasId(within(select('c').union(__.id(), repeat(__.in('hasChild')).emit().id()))))
.select('d', 'm')

I get the following error (this is on Neptune)

Expected an id that is convertible to String but received class com.amazon.neptune.tinkerpop.structure.NeptuneGraph$NeptuneGraphTraversal

Upvotes: 1

Views: 1127

Answers (1)

Kelvin Lawrence
Kelvin Lawrence

Reputation: 14371

So, hasId can only accept a list of one or more ID values and within is a Predicate (P) and can only take a list of values or a Collection of values not a traversal. You will need to restructure your query a little to build a collection first, perhaps using aggregate and then do something like

where(eq('a')).by(id)

or

where(within('a'))

Where 'a' is either a collection of vertices in the first case or a collection of vertices or id values in the second.

Upvotes: 1

Related Questions