java - 泰坦图用例中的 GremlinPipeLine java API 链遍历

标签 java titan gremlin graph-traversal

我有一个用例,其中我必须遍历从特定顶点开始的顶点链。它是一个线性链(如火车),只有一个顶点连接到前一个。在遍历时,我必须根据某些标准发出某些顶点,直到到达链的末端。

第二个用例是上述用例的扩展,但不是从单个顶点开始的单个链,而是多个这样的链,同样从单个顶点开始。我必须遍历每个链并检查顶点中的特定属性值。当找到该属性匹配时,我必须发出该顶点并以第二条链开头,依此类推。

我必须使用 Gremlin java API 来实现。这看起来很简单,但我是 gremlin 的新手,并且在 gremlin java API 上互联网上也没有太多帮助。

最佳答案

将 Gremlin Groovy 转换为 Gremlin Java 应该不是很困难。我总是反对按照你的意愿去做:

  • 大大增加您的代码大小
  • 降低代码可读性
  • 让你的代码更难维护

  • 如果你在一个听不到外部编程语言的“Java 商店”工作,我认为通过 Gremlin 在 groovy 和 java 中的差异的几个例子向人们推销这些点并不太难(容易理解)阅读一个类轮与可能是数百行代码的内容)。此外,Groovy 可以与 Java 一起放入同一模块中的标准 Maven 项目中,也可以放入其他项目所依赖的单独的独立模块中。在大多数情况下,我更喜欢后者,因为您将 groovy 隔离在单个包中,并且可以在多个用例(例如应用程序、gremlin 控制台中的附加库等)中作为 DSL 重用。

    也就是说,如果您仍然必须使用 Java,我仍然会从编写 Groovy 开始。使用 Gremlin 控制台并获得正确的遍历算法。听起来好像您的两个用例都涉及循环,所以我们只会说您的遍历看起来像:
    g.v(1).out.loop(1){true}{it.object.someProperty=="emitIfThis"}
    

    所以这将从顶点“1”遍历链,直到我用尽链,在第一个闭包中用“true”表示,然后在第二个闭包中发出与我的条件匹配的任何顶点。一旦您定义并测试了大量 Gremlin,就可以转换为 Java。

    如您所知,以 GremlinPipeline 开头第一部分很容易用于转换目的:
    new GremlinPipeline(g.getVertex(1)).out()
    

    如您所见,Groovy 方法几乎可以相当干净地映射到 Java,直到您需要一个闭包和 loop是需要一个步骤的步骤之一。要使用 Gremlin Java,您可能会发现查看 javadoc 很有用。为 GremlinPipeline .

    我使用了 loop 的三参数版本- 标记为“已弃用”的那个(但对于我们的目的来说没问题)- 你可以看到它 here .第一个参数很简单 - 一个整数,所以翻译的第一部分是:
    new GremlinPipeline(g.getVertex(1)).out().loop(1, closure, closure)
    

    我已经为我们拥有的另外两个闭包留下了占位符。如果你这样看,它真的与我们的 Groovy 版本没有什么不同——只是语法略有不同。

    在 Java 8 之前,Java 语言中没有内置闭包的概念。请注意,在 TinkerPop3 ,Gremlin 发生了巨大变化,以利用我们现在拥有 lambda 的事实。但是当你在 TinkerPop2 中时,你必须使用内置的 PipeFunction它本质上代表了我们 groovy 闭包的类型版本。 PipeFunction循环的两个参数是:
    PipeFunction<LoopPipe.LoopBundle<E>,Boolean>
    

    所以基本上,这是一个获取 LoopPipe.LoopBundle 的函数作为包含有关循环的元数据并期望您返回 boolean 值的对象。如果你理解了这个概念,那么所有 Gremlin Java 都会为你打开,因为在你看到 groovy 闭包的任何地方,你都知道在它下面只是某种形式的 PipeFunction在 Java 中,鉴于您现在可以阅读 PipeFunction 的期望值从 javadocs 中,进行这些语言翻译应该很简单。

    我们必须做的第一个闭包翻译非常简单 - 我们只需要我们的 PipeFunction返回 true :
    new GremlinPipeline(g.getVertex(1)).out().loop(1, 
        new PipeFunction<LoopPipe.LoopBundle<Vertex>,Boolean>() {
            public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
                return true;
            }
        }, closure)
    

    因此,对于 loop 的第二个参数我们必须构建一个新的 PipeFunction ,它有一个方法叫做 compute .从那个方法我们返回 true .现在处理第二个 PipeFunction控制顶点发射的参数:
    new GremlinPipeline(g.getVertex(1)).out().loop(1, 
        new PipeFunction<LoopPipe.LoopBundle<Vertex>,Boolean>() {
            public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
                return true;
            }
        }, 
        new PipeFunction<LoopPipe.LoopBundle<Vertex>,Boolean>() {
            public Boolean compute(LoopPipe.LoopBundle<Vertex> argument) {
                return argument.getObject().getProperty("someProperty").equals("emitIfThis");
            }
        })
    

    这就是转换。由于这是一篇很长的文章,让我们将原始 groovy 放在更靠近上面的位置,以便清楚区别:
    g.v(1).out.loop(1){true}{it.object.someProperty=="emitIfThis"}
    

    我们从上面的一行代码变成了将近一打的代码,否则非常简单。鉴于 lambda 表达式和语言本身的重大改革,Gremlin Java 在 TinkerPop3 中独树一帜,但是当 Groovy 可以使事情变得非常整洁时,这些先前版本产生的 Java 代码确实不值得为生成或维护付出努力。

    关于java - 泰坦图用例中的 GremlinPipeLine java API 链遍历,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29409219/

    相关文章:

    java - JSP 异常, "quote symbol expected"

    amazon-dynamodb - 无法创建复合索引,卡在 INSTALLED

    javascript - 如何重用 Javascript 中的函数链?

    java - 通过 Lambda 函数添​​加KeyListener

    java - DecimalFormat 变量组大小

    java - 使用 JWS JNLP 为 JavaFX 应用创建桌面图标

    java - 使用 GremlinPipeline 查找最短路径

    ibm-cloud - Titan 中数据类型的最佳实践是什么?

    cassandra - Janusgraph 后端表的布局

    gremlin - 如何在 Gremlin 中查找同一天参加同一研讨会的人员边缘列表?