When you write Gremlin you need to think in terms of streams. V()
produces a stream of all vertices in the graph. Envision each item in that stream hitting hasLabel()
and has()
filters to be paired away until they hit the reducing step of fold()
which produces a List
with vertices that match the filter criteria or, if there are none, it simple produces an empty list which becomes the new object in the stream.
From there coalesce()
produces an if-then sort of case where the first child stream provided to it that returns a value ends up being exhausted and the remaining child streams ignored. Therefore, if unfold()
which takes the List
with vertices produced by fold()
contains a vertex, then it is provided to the stream and that vertex exists and coalesce()
thus produces that existing vertex and goes on to the final two steps of property("value", "A").property("action", "update")
. If the List
is empty then the unfold()
stream produces no objects and goes to the next child stream which starts with addV()
. The addV()
stream will obviously produce a new Vertex
with the specified properties, but then coalesce()
as its parent will produce that newly added vertex to the stream and it too will continue to those final two steps and thus overwrite the property values you provided to addV()
.
If you want to have two separate paths, then you might do something like this:
g.V().hasLabel("Entity").has("identifier", "123").fold()
.coalesce((Traversal)
__.unfold()
.property("value", "A")
.property("action", "update"),
__.addV("Entity")
.property("identifier", "123")
.property("value", "A")
.property("action", "add")
)
.iterate();