【问题标题】:How to collect optional branches in TinkerPop3?如何在 TinkerPop3 中收集可选分支?
【发布时间】:2023-10-07 11:44:01
【问题描述】:

我有一个看起来像这样的图表:

使用gremlin-scala,我试图从 A 遍历并收集这些元组:

(A, Some(A1)), (B, None), (C, Some(A2))

所以本质上,我想反复取α 出边,并可选择分支到β,收集这些出边。我猜如果没有 β 边缘,我需要注入一个空的“步骤”,但我无法弄清楚如何做到这一点。

由于jump 已被神秘删除(TP 3.1+),我也对遍历β 后如何倒带有些困惑(TP 3.1+)

到目前为止,我有类似的东西:

graph.V("A").untilWithTraverser(t => t.get.outE(α).notExists()
    ).repeat(_.out(α).as(foo).out(β).as(bar)).select((foo,bar)).toList

但是如果“主干”上的任何节点缺少β out 边缘,这不会倒回到主遍历并且失败

【问题讨论】:

    标签: scala orientdb gremlin tinkerpop tinkerpop3


    【解决方案1】:

    我无法提供 gremlin-scala 解决方案,但您应该很容易转换以下 Groovy 示例:

    g.V("A").until(__.not(outE("alpha"))).
               repeat(out("alpha")).path().by(union(identity(), out("beta")).fold())
    

    这将返回:

    [[A, A1], [B], [C, A2]]
    

    国际海事组织这就足够了。但是,如果您需要一组一致的 2 个条目,则可以执行以下操作:

    g.V("A").until(__.not(outE("alpha"))).repeat(out("alpha")).
      path().by(union(identity(), coalesce(out("beta"), constant("N/A"))).fold())
    

    ...然后将返回:

    [[A, A1], [B, N/A], [C, A2]]
    

    完成会话:

    http://gremlinbin.com/bin/view/57133bdc8ee00

    【讨论】:

      【解决方案2】:

      这是我的 gremlin-scala 解决方案,基于 Daniel 的回答。

      val unionTraversal = __[(String, Vertex)].union(
        __[Vertex].identity.map("blob" -> _),
        __.out(Beta).map("beta" -> _)
      ).traversal
      
      def pathTuplesToScalaTuples(path: Path) =
        path.objects.asScala.map(_.asInstanceOf[java.util.ArrayList[(String, Vertex)]].asScala.toList).toList
      
      val pathO = graph.V("A")
          .until(_.not(_.out(Alpha)))
          .repeat(_.out(Alpha))
          .path.by(unionTraversal.fold).headOption
      val tuples = pathO.map(pathTuplesToScalaTuples)
      

      不幸的是,这涉及到几个问题才能真正使发射的顶点有用。

      首先,当将匿名遍历传递给联合时,步骤标签会被删除,因此您无法使用 .as("blob") 标记您发出的集合——这就是使用字符串标签将它们包装在元组中的解决方法。

      其次,gremlin-scala 还没有 Path 的包装器(并且可能永远不会得到它,因为路径可以有任意结构)所以我们必须做一个丑陋的演员表。

      【讨论】: