为什么遍历结果会一步一步改变,而只保留一个结果?

时间:2019-01-29 04:19:25

标签: graph gremlin tinkerpop3 graph-traversal

我正在构建一个API,以在我的janusgraph数据库中获取和组织一些信息,但是对于gremlin查询我还是比较陌生。我想知道为什么在组步骤的第二步中遍历会返回一些关于图的不完整信息

查询是从gremlin python驱动程序发送的,就好像它们是gremlin查询一样。起初我以为问题是与问题相关的,但是后来我直接从gremlin终端(从bin / gremlin.sh运行)尝试了,结果是相同的,因此我认为这不是错误,而是如何它是预期的。很好,但是我想了解为什么查询会导致这种情况,以及如何构建适合我需求的查询。

在示例中,我仅对项目步骤使用一个步骤,但在实际问题中,我打算使用多个步骤,例如:

(...).project('key1', 'key2', 'key3').by(...).by(...).by(...)

初始配置:

gremlin> g.V().has('name', 'fiber')
==>v[1]
==>v[2]

gremlin> g.V(1).in()
==>v[10]

gremlin> g.V(2).in()
==>v[20]


gremlin> g.V().has('name', 'fiber').in()
==>v[10]
==>v[20]

这就是我得到的:

gremlin> g.V().has('name', 'fiber').group().by('name').by(project('amount').by(__.in().count()))
==>{fiber={amount=1}}

gremlin> g.V().has('name','fiber').group().by('name').by(__.in().count())
==>{fiber=2}

gremlin> g.V().has('name', 'fiber').group().by('name').by(__.in())
==>{fiber=v[20]}

gremlin> g.V().has('name', 'fiber').group().by('name')
==>{fiber=[v[1], v[2]]}

这就是我所期望的:

gremlin> g.V().has('name', 'fiber').group().by('name').by(project('amount').by(__.in().count()))
==>{fiber={amount=2}}

gremlin> g.V().has('name','fiber').group().by('name').by(__.in().count())
==>{fiber=2}

gremlin> g.V().has('name', 'fiber').group().by('name').by(__.in())
==>{fiber=[v[10], v[20]]}

gremlin> g.V().has('name', 'fiber').group().by('name')
==>{fiber=[v[1], v[2]]}

1 个答案:

答案 0 :(得分:4)

如您所见,这只是Gremlin中的设计选择,而不是bug。 by()调制器仅对作为其参数传递的匿名next()调用Traversal,除非您明确告知,否则不会费心将整个对象迭代到列表中。我还没有特别记得by(Traversal)能够以这种方式工作的所有原因,但总的来说,我认为让Gremlin假设用户希望匿名遍历进行尽可能少的工作是比较安全的。如果您希望它做更多,请告诉Gremlin您希望它做更多。

因此对于此示例:

g.V().has('name', 'fiber').group().by('name').by(__.in())

如果要获得所有in()个顶点,则需要告诉Gremlin明确收集该顶点:

g.V().has('name', 'fiber').group().by('name').by(__.in().fold())

请注意,by()并不是那样工作的唯一步骤,而Gremlin尽了最大的努力实际上是一种便利,它可以减少使用emit()调制器(例如{ {1}}步骤:

repeat()

除了键入更少之外,其阅读效果还比:

g.V().repeat(out()).emit(outE())

我还认为,在g.V().repeat(out()).emit(outE().limit(1).count().is(1)) (以及其他以by()作为参数的步骤/调制器)的行为下,Gremlin并不需要过多地假设您想要数据结果看起来像。如果Traversal始终被完全迭代,则意味着您将始终得到Traversal作为输出,而输出可能不是您想要的。然后,您将需要解开列表并丢弃该列表-因此Gremlin将创建一个仅将其扔给GC的对象。

List起作用的原因可能还有其他原因(主要是更具体的原因),但是希望这种解释使您对为什么它是如此的想法有所了解。