0

I'm trying to create an upsert traversal in Gremlin. Update an edge if it exists, otherwise add a new edge.

g.V("123")
.as("user")
.V("456")
.as("post")
.inE("like")
.fold()
.coalesce(
  __.unfold()
  .property("likeCount", 1),
  __.addE("like")
  .from("user")
  .to("post")
)

This returns an error.

The provided traverser does not map to a value: []->[SelectOneStep(last,post)]

I've narrowed this down to the to("post") step. From within coalesce it can't see post from as("post"). It is also unable to see user.

This is strange to me because the following does work:

g.V("123")
.as("user")
.V("456")
.as("post")
.choose(
  __.inE("like"),
  __.inE("like")
    .property("likeCount", 1),
  __.addE("like")
    .from("user")
    .to("post")
)

From within the choose() step I do have access to user and post.

I'd like to use the more efficient upsert pattern but can't get past this issue. I could just look up the user and post from within coalesce like so:

g.V("123")
.as("user")
.V("456")
.as("post")
.inE("like")
.fold()
.coalesce(
  __.unfold()
  .property("likeCount", 1),
  __.V("456")
  .as("post")
  .V("123")
  .addE("like")
  .to("post")
)

But repeating that traversal seems inefficient. I need post and user in the outer traversal for other reasons.

Why can't I access user and post from within a coalesce in my first example?

Fook
  • 5,320
  • 7
  • 35
  • 57

1 Answers1

1

The issue you are running into is that as soon as you hit the fold() step in your code you lose the path history, which means that it will not know user or post are referring to. fold() is what is known as a ReducingBarrierStep which means that many results are collected into a single result. The way I think about it is that because you have converted many results to one, anything like aliases that were added (e.g. user and post) no longer really have meaning as they have all been collected into a single element.

However you can rewrite your query as shown here to achieve the desired result:

g.V("456")
.inE("like")
.fold()
.coalesce(
  __.unfold()
  .property("likeCount", 1),
  __.addE("like")
  .from(V("123"))
  .to(V("456"))
)

I am also not sure if you meant to only add a like count on an existing edge or if you wanted to add the like count to the edge in either case which would be like this:

g.V("456")
.inE("like")
.fold()
.coalesce(
  __.unfold(),
  __.addE("like")
  .from(V("123"))
  .to(V("456"))
).property("likeCount", 1)
bechbd
  • 6,206
  • 3
  • 28
  • 47
  • Thanks for the explanation. I oversimplified the example a bit too much and the `count` step didn't make sense. – Fook Jul 02 '21 at 21:04