提供的遍历未映射到值

The provided traversal does not map to a value

我正在尝试执行数学查询。

gts.V()
.hasLabel("account")
.has("id",42)
.both("account_label1").as("label1")
.and(__.identity()
        .project("a","b")
        .by(__.identity()
                .both("label1_label2")
                .both("label2_label3")
                .values("createTime"))
        .by(__.identity()
                .both("label1_label4")
                .both("label4_label5")
                .values("launchTime"))
        .math("floor((a-b)/(86400))").is(100))
.select("label1")
.toList()

以上查询因错误而失败

The provided traverser does not map to a value: v[137]->[IdentityStep, VertexStep(BOTH,[label1_label2],vertex), VertexStep(BOTH,[label2_label3],vertex), NoOpBarrierStep(2500), PropertiesStep([createTime],value)]
  1. 为什么gremlin注入是NoOpBarrierStep?
  2. NoOpBarrierStep(2500)是什么意思?
  3. 相同的正确 gremlin 查询是什么?

当您使用 project() 时,它期望每个 by() 调制器都有一个值,并且该值不应产生空的 Iterator。这是一个简单的例子:

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().project('x').by(out())
==>[x:v[3]]
The provided traverser does not map to a value: v[2]->[VertexStep(OUT,vertex)]
Type ':help' or ':h' for help.
Display stack trace? [yN]

第一个顶点能够遍历 out(),但 project() 处理的下一个顶点没有出边,因此产生此错误。在您的情况下,这仅意味着并非所有遍历器都可以遍历 both().both() 或者如果可以,您将希望确保它们都具有“createTime”属性 值。这些情况中的任何一种都可能导致问题。

您可以通过多种方式解决此问题。显然,如果这是一个数据问题,您可以简单地修复您的数据并始终假设遍历路径是正确的。如果不是这种情况,则在遍历路径不可用时,您需要将 Gremlin 编写得更宽容一些。就我而言,我可以这样做:

gremlin> g.V().project('x').by(out().fold())
==>[x:[v[3],v[2],v[4]]]
==>[x:[]]
==>[x:[]]
==>[x:[v[5],v[3]]]
==>[x:[]]
==>[x:[v[3]]]

也许在你的情况下你可以这样做:

by(coalesce(both("label1_label2").both("label2_label3").values("createTime"),
            constant('n/a')))

请注意,您不需要为匿名遍历的开始指定 identity()

最后,在回答您关于 NoOpBarrierStep 的问题时,该步骤被注入到 Gremlin 认为它可以利用 bulking optimization 的遍历中。您也可以使用 barrier() 步骤自己添加它们。以下是从 TinkerPop 参考文档中获取的对“批量”的快速描述:

The theory behind a "bulking optimization" is simple. If there are one million traversers at vertex 1, then there is no need to calculate one million both()-computations. Instead, represent those one million traversers as a single traverser with a Traverser.bulk() equal to one million and execute both() once.