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

use*_*615 4 java graph-traversal gremlin titan

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

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

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

ste*_*tte 10

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

  1. 大大增加代码的大小
  2. 使您的代码可读性降低
  3. 使您的代码更难维护

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

也就是说,如果你仍然必须使用Java,我仍然可以从编写Groovy开始.使用Gremlin控制台并正确获取遍历算法.听起来好像你的两个用例都涉及循环,所以我们只是说你的遍历看起来像:

g.v(1).out.loop(1){true}{it.object.someProperty=="emitIfThis"}
Run Code Online (Sandbox Code Playgroud)

这将从顶点"1"遍历链,直到我耗尽链,在第一个闭包中用"true"表示,然后在第二个闭包中发出符合我标准的任何顶点.一旦你有大量的Gremlin定义和测试,就可以转换为Java了.

如您所知,以a GremlinPipeline和第一部分开头非常容易进行转换:

new GremlinPipeline(g.getVertex(1)).out()
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,Groovy方法几乎可以非常干净地映射到Java,直到您需要一个闭包并且loop是需要一个闭包的步骤之一.要使用Java的小鬼工作,你可能会发现它很有用看的javadocGremlinPipeline.

我使用了三个参数版本loop- 标记为"已弃用"的版本(但这对我们来说没问题) - 你可以在这里看到它.第一个参数很简单 - 一个整数,所以翻译的第一部分是:

new GremlinPipeline(g.getVertex(1)).out().loop(1, closure, closure)
Run Code Online (Sandbox Code Playgroud)

我已经将占位符留给了我们拥有的另外两个封口.如果以这种方式看待它,它与我们的Groovy版本没有什么不同 - 语法略有不同.

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

PipeFunction<LoopPipe.LoopBundle<E>,Boolean>
Run Code Online (Sandbox Code Playgroud)

所以基本上,这是一个函数,它获取一个LoopPipe.LoopBundle包含循环元数据的对象,并期望返回一个布尔值.如果你理解了这个概念,那么所有的Gremlin Java都会为你打开,因为你看到一个groovy闭包的地方,你知道它下面只是PipeFunctionjava中的某种形式,并且你现在可以从中读取a的期望了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)
Run Code Online (Sandbox Code Playgroud)

所以,对于第二个参数,loop我们必须构造一个new 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");
        }
    })
Run Code Online (Sandbox Code Playgroud)

并且存在转换.由于这是一个很长的帖子,让我们把原始的groovy放在更接近上面的位置,这样差别很明显:

g.v(1).out.loop(1){true}{it.object.someProperty=="emitIfThis"}
Run Code Online (Sandbox Code Playgroud)

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