简体   繁体   中英

Upsert of Vertices and Edge in a single Traversal in Gremlin

I've been trying for several hours to write a gremlin statement to handle upserting 2 vertices and 1 edge between them, without much luck.

in pseudo-gremlin what I want to do is pretty straightforward and is the following:

g.V()
.hasLabel("person")
.has("custom_id", "123")
.fold()
.coalesce(
  __.unfold().property(single, "name", "Tom"), 
  __.addV("person").property(single, "custom_id", "123").property(single, "name", "Tom"))
.as("fromStep")
.V()
.hasLabel("person")
.has("custom_id", "654")
.fold()
.coalesce(
  __.unfold().property(single, "name", "Sally"),
  __.addV("person").property(single, "custom_id", "654").property(single, "name", "Sally"))
.as("toStep")
.E()
.hasLabel("knows")
.where(__.inV().is("fromStep"))
.where(__.outV().is("toStep"))
.fold()
.coalesce(
  __.unfold().property("since", "2020-01-01"),
  __.addE("knows").property("since", "2020-01-01").from("fromStep").to("toStep")

The problem with this code is that each fold step, being a barrier step "removes" the value of the previous as steps.

Is there a way to do this properly in a single statement?

SOLUTION

Thanks to Kelvin answer's here's the solution:)

g.V()
.hasLabel("person")
.has("custom_id", "123")
.fold()
.coalesce(
    __.unfold().property(single, "name", "Tom"), 
    __.addV("person").property(single, "custom_id", "123").property(single, "name", "Tom"))
.store("a")
.V()
.hasLabel("person")
.has("custom_id", "654")
.fold()
.coalesce(
    __.unfold().property(single, "name", "Sally"),
    __.addV("person").property(single, "custom_id", "654").property(single, "name", "Sally"))
.store("b")
.fold()
.select("a").unfold().as("from")
.select("b").unfold().coalesce(
    __.inE("knows").where(__.outV().as("from")).property("since", "2020-01-01"),
    __.addE("knows").property("since", "2020-01-01").from("from")
)

As you noted, labels applied using an as step are lost after a barrier/map step like fold is used. However, store and aggregate bulk sets will survive intact. Here is a simple pattern that works after a fold that you should be able to adapt for your use case. As we discussed in the comments, if you knew the ID of the vertices you were searching for and if the ID was not found you created it that would give you another way to approach this. Anyway, here is one way that works in the presence of a fold step.

gremlin> g.V('3').store('a').
......1>   V('4').store('b').
......2>   fold().
......3>   select('a').unfold().as('from').
......4>   select('b').unfold().as('to').
......5>   addE('test').
......6>     from('from').
......7>     to('to')    

==>e[60876][3-test->4] 

One other note, in general mid traversal E steps are not supported. It really should be written as V().outE()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM