在 Gremlin 中 map() 是如何工作的?

In Gremlin how does map() really work?

为什么这两个会产生不同的结果?

graph.traversal()
   .V().map(__.out("contains"))
.valueMap(true).next(100)

相比
graph.traversal()
   .V().out("contains")
.valueMap(true).next(100)

为什么我更喜欢 map 而不是直接调用 .out() 方法? 这样我就可以组织我的代码,在其中我可以从方法和 "map" 到现有遍历进行遍历。

在考虑这个问题时,回想一下 Gremlin 有点像一个处理管道,其中对象被拉过管道中的每个步骤以应用一些转换、过滤器等。所以,以最简单的方式给出你的例子形式你会说你正在获取所有顶点并遍历 out() 边,这意味着你正在比较以下遍历和结果:

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().out()
==>v[3]
==>v[2]
==>v[4]
==>v[5]
==>v[3]
==>v[3]
gremlin> g.V().map(out())
==>v[3]
==>v[5]
==>v[3]

这些遍历 return 两个不同的结果,因为您向 Gremlin 询问两个不同的事情。在第一种情况下,out() 不是 map() 的一种形式,它是 flatMap() 的一种形式,这意味着对于每个通过管道的顶点遍历器,它将迭代所有出边和遍历并 return 相邻顶点(即一对多变换)。在第二种情况下,您要求 Gremlin 对另一个对象执行一个简单的 map() 顶点(即一对一变换),在这种情况下,这将是 out() 的结果,即该遍历器流中的第一个对象。

为了演示,您可以简单地将 map() 更改为 flatMap(),如下所示:

gremlin> g.V().flatMap(out())
==>v[3]
==>v[2]
==>v[4]
==>v[5]
==>v[3]
==>v[3]

或者 fold() out() 的结果到单个对象以保持一对一转换逻辑:

gremlin> g.V().map(out().fold())
==>[v[3],v[2],v[4]]
==>[]
==>[]
==>[v[5],v[3]]
==>[]
==>[v[3]]