为什么需要对有条件的插入使用合并折叠/展开?

时间:2018-08-10 10:25:38

标签: gremlin tinkerpop3

我试图了解条件插入的这种模式是如何工作的:

g.V()
  .hasLabel('person').has('name', 'John')
  .fold()
  .coalesce(
    __.unfold(),
    g.addV('person').property('name', 'John')
  ).next();

折叠/展开的目的是什么?为什么这些是必需的,为什么它不起作用:

g.V()
  .coalesce(
    __.hasLabel('person').has('name', 'John'),
    g.addV('person').property('name', 'John')
  ).next();

“折叠-然后-展开”模式对我来说似乎是多余的,但是上述方法并不会产生相同的结果。

1 个答案:

答案 0 :(得分:10)

考虑一下以下操作会发生什么:

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().has('name','marko')
==>v[1]
gremlin> g.V().has('name','stephen')
gremlin> 

对于“ marko”,您返回某些内容,对于“ stephen”,您不返回某些内容。 “斯蒂芬”案例是要注意的一个案例,因为在这种情况下,fold()确实变得非常重要。当遍历不返回任何内容时,此后添加的任何步骤都不会出现Traverser来触发这些步骤中的操作。因此,即使是以下情况也不会添加顶点:

gremlin> g.V().has('name','stephen').addV('person')
gremlin> 

但是,如果我们fold()

gremlin> g.V().has('name','stephen').fold()
==>[]

fold()是减少障碍的步骤,因此将急切地评估到该点的遍历,并将内容返回为List,即使该遍历的内容到那个点都没有产生任何收益(在如您所见,在这种情况下,您会得到一个空列表)。而且如果您有一个空List,那么该空List就是一个遍历遍历的Traverser,因此将来的步骤将会触发:

gremlin> g.V().has('name','stephen').fold().addV('person')
==>v[13]

所以这说明了为什么我们fold(),因为我们正在检查示例中是否存在“约翰”,如果找到了他,则他将存在于List中,并且当List与“约翰”击中coalesce()的第一项检查将是将unfold()与“约翰”一起List并返回Vertex-完成。如果List为空并且由于不存在“ John”而未返回任何内容,则它将添加顶点(顺便说一句,您不需要在addV()前面加上“ g”。应该只是匿名遍历,因此__.addV('person'))。

以您的示例为例,我首先要指出的是,我想您想问一下这个问题:

g.V().
  coalesce(
    __.has('person','name', 'John'),
    __.addV('person').property('name', 'John'))

这是一个完全不同的查询。在此遍历中,您要迭代所有顶点,并为每个顶点执行coalesce()中的内容。通过将addV()替换为constant('x'),可以很清楚地看到这一点:

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().
......1>   coalesce(
......2>     has('person','name', 'John'),
......3>     constant('x'))
==>x
==>x
==>x
==>x
==>x
==>x
gremlin> g.V().
......1>   coalesce(
......2>     has('person','name', 'marko'),
......3>     constant('x'))
==>v[1]
==>x
==>x
==>x
==>x
==>x

现在,想象一下addV()和“ John”会发生什么。它将调用addV() 6次,每遇到一个不是“ John”的顶点,就会调用一次:

gremlin> g.V().
......1>   coalesce(
......2>     __.has('person','name', 'John'),
......3>     __.addV('person').property('name', 'John'))
==>v[13]
==>v[15]
==>v[17]
==>v[19]
==>v[21]
==>v[23]

我个人比较喜欢将这种逻辑封装在Gremlin DSL中的想法-有一个很好的例子here

一个很好的问题-我已经将“元素存在”问题描述为可以阅读here的Gremlin食谱的一部分。