我试图了解条件插入的这种模式是如何工作的:
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();
“折叠-然后-展开”模式对我来说似乎是多余的,但是上述方法并不会产生相同的结果。
答案 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食谱的一部分。