在 Gremlin 的一次遍历中更新顶点和边
Upsert of Vertices and Edge in a single Traversal in Gremlin
我已经尝试了几个小时来编写一个 gremlin 语句来处理 upserting 2 个顶点和它们之间的 1 个边,但运气不佳。
在 pseudo-gremlin 中,我想做的非常简单,如下所示:
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")
此代码的问题在于每个 fold
步骤作为障碍步骤都会“删除”之前 as
步骤的值。
有没有办法在一条语句中正确地做到这一点?
解决方案
感谢 Kelvin 的回答,这里是解决方案:)
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
步骤应用的标签在使用 barrier/map 步骤(如 fold
)后会丢失。但是,store
和 aggregate
批量集将完好无损。这是一个在 fold
之后工作的简单模式,您应该能够适应您的用例。正如我们在评论中讨论的那样,如果您知道要搜索的顶点的 ID,并且如果未找到该 ID,则可以创建它,这将为您提供另一种方法来解决这个问题。无论如何,这是一种在存在 fold
步骤的情况下有效的方法。
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]
另一个注意事项,一般来说中间遍历 E
个步骤不受支持。确实应该写成V().outE()
我已经尝试了几个小时来编写一个 gremlin 语句来处理 upserting 2 个顶点和它们之间的 1 个边,但运气不佳。
在 pseudo-gremlin 中,我想做的非常简单,如下所示:
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")
此代码的问题在于每个 fold
步骤作为障碍步骤都会“删除”之前 as
步骤的值。
有没有办法在一条语句中正确地做到这一点?
解决方案
感谢 Kelvin 的回答,这里是解决方案:)
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
步骤应用的标签在使用 barrier/map 步骤(如 fold
)后会丢失。但是,store
和 aggregate
批量集将完好无损。这是一个在 fold
之后工作的简单模式,您应该能够适应您的用例。正如我们在评论中讨论的那样,如果您知道要搜索的顶点的 ID,并且如果未找到该 ID,则可以创建它,这将为您提供另一种方法来解决这个问题。无论如何,这是一种在存在 fold
步骤的情况下有效的方法。
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]
另一个注意事项,一般来说中间遍历 E
个步骤不受支持。确实应该写成V().outE()