I have person
vertex, has_vehicle
edge and vehicle
vertex which models vehicle ownership use case. The graph path is person -> has_vehicle -> vehicle
.
I want to implement a Gremlin query which associates a vehicle to a person only if
AND
I followed the fold-coalesce-unfold pattern and came out with following Gremlin query with nested coalesce
g.V().hasLabel('person').has('name', 'Tom').as('Tom').outE('has_vehicle').fold().coalesce(
__.unfold(), // check if Tom already have a vehicle
g.V().has('vehicle', 123).as('Vehicle').inE('has_vehicle').fold().coalesce(
__.unfold(), // check if vehicle 123 is already associated with a person
__.addE('has_vehicle').from('Tom').to('Vehicle') // associate the vehicle to Tom
)
)
Is there a way to eliminate the nested coalesce? If I have multiple criteria, it would be too complex to write the query.
This might be a case where a couple of where(not(...))
patterns, rather than nesting coalesce
steps works well. For example, we might change the query as shown below.
g.V().hasLabel('person').has('name', 'Tom').as('Tom').
where(not(outE('has_vehicle'))).
V().has('vehicle', 123).as('Vehicle').
where(not(inE('has_vehicle'))).
addE('has_vehicle').from('Tom').to('Vehicle')
So long as the V
steps do not fan out and yield multiple Tom or Vehicle nodes that should work and is easy to extend by adding more to the where
filters as needed.
As as a side note, the not
steps used above should work even if not wrapped by where
steps, but I tend to find it just reads better as written.
This rewrite does make an assumption that you are able to tolerate the case where Tom already has a car and the query just ends there. In that case no vertex or edge will be returned. If you did a toList
to run the query you would get an empty list back in that case however to indicate nothing was done.