首页 文章

GremlinPipeLine在Titan图形用例中的java API链遍历

提问于
浏览
4

我有一个用例,我必须从一个特定的顶点开始遍历一串顶点 . 它是一个线性链(像火车),只有一个顶点连接到前一个 . 虽然遍历我必须根据一些标准发射某些顶点,直到我到达链的末端 .

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

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

1 回答

  • 10

    将Gremlin Groovy转换为Gremlin Java应该不是很困难 . 我总是反对这样做:

    • 大大增加代码的大小

    • 使您的代码可读性降低

    • 使您的代码更难维护

    如果你在一个不会听到外部编程语言的“Java商店”工作,我认为仅仅通过几个例子来说明Gremlin在groovy和java中的差异就很难卖掉那些人(很容易阅读一个内衬与可能是数百行代码的内容 . 此外,Groovy可以在同一模块中与java一起使用,也可以在其他项目所依赖的独立模块中适用于标准Maven项目 . 在大多数情况下,我更喜欢后者,因为您在单个包中隔离了groovy,并且在多个用例中可以重复使用DSL(例如,应用程序,gremlin控制台中的附加库等) .

    也就是说,如果你仍然必须使用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 for GremlinPipeline 非常有用 .

    我使用了 loop 的三个参数版本 - 标记为"deprecated"的那个(但是我们的目的没问题) - 你可以看到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 作为一个包含循环元数据的对象,并期望返回一个布尔值 . 如果你理解了这个概念,那么所有的Gremlin Java都会为你打开,因为你看到一个groovy闭包的地方,你知道它下面只是java中某种形式的 PipeFunction ,并且你现在可以阅读 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"}
    

    我们从上面的一行代码转到了近十几行,这是一个非常简单的遍历 . Gremlin Java在TinkerPop3中自成一体,给出了lambdas和语言本身的重大改进,但是这些先前的版本产生的java代码在Groovy可以使事情非常整洁时非常值得生成或维护 .

相关问题