2015-04-02 52 views
4

我有使用情況,我必須遍歷從特定頂點開始的一系列頂點。它是一個線性鏈(像火車),只有一個頂點與前一個連接。在遍歷時,我必須根據某些條件發出某些頂點,直到到達鏈的末端。GremlinPipeLine在Titan圖形用例中的java API鏈遍歷

第二個用例是上述用例的擴展,但不是從單個頂點開始的單個鏈,而是從多個頂點開始的多個鏈。我必須遍歷每個鏈,並檢查頂點中的特定屬性值。當找到屬性匹配時,我必須發出該頂點,並從第二條鏈開始,等等。

我必須使用Gremlin java API來實現。這似乎是一個簡單的問題,但我是gremlin的新手,並且互聯網上沒有太多關於gremlin java API的幫助。

+1

你所描述的是'方法鏈'。如果您想要API鏈接,請參閱規範(https://github.com/orubel/grails-api-toolkit-docs/wiki/API-Chaining)或其上的springone演示文稿(http://www.slideshare.net/bobdobbes/api-abstraction-api-chaining) – Orubel 2015-04-23 22:29:08

回答

10

將Gremlin Groovy轉換爲Gremlin Java應該不是很困難。我總是會反對這樣做,你會:

  1. 大大增加你的代碼的大小
  2. 使您的代碼的可讀性
  3. 使您的代碼更難維護

如果你工作在一家不會聽到外部編程語言的「Java商店」中,我認爲在這些問題上銷售人員並不難,只需要少量Gremlin在groovy和java中的差異示例(易於閱讀一個內容與幾百行代碼相比)。此外,Groovy可以放入一個標準的Maven項目中,或者與同一模塊中的java一起使用,也可以放入其他項目所依賴的單獨獨立模塊中。在大多數情況下,我更喜歡後者,因爲您將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,您可能會發現查看javadocGremlinPipeline很有用。

我使用了三個參數版本loop - 標記爲「已棄用」(但對我們來說沒關係) - 您可以看到它here。第一個理由很簡單 - 一個整數,所以翻譯的第一部分是:

new GremlinPipeline(g.getVertex(1)).out().loop(1, closure, closure) 

我已經離開的地方持有人,我們有其他兩個關閉。如果你以這種方式來看待它,它與我們的Groovy版本沒有什麼不同 - 語法稍有不同。

在Java 8之前,沒有內置到java語言中的閉包的概念。請注意,在TinkerPop3中,Gremlin發生了巨大變化,以利用我們現在擁有lambda的事實。但是當你在TinkerPop2中時,你必須使用PipeFunction中的內置函數,它基本上代表了我們常規閉包的類型化版本。該PipeFunction兩個參數循環是:

PipeFunction<LoopPipe.LoopBundle<E>,Boolean> 

所以基本上,這是得到一個LoopPipe.LoopBundle因爲其中包含有關環路的元數據,並期望你返回一個布爾值對象的功能。如果你理解了這個概念,那麼所有的Gremlin 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"); 
     } 
    }) 

還有矗立的轉換。由於這是一個很長的帖子,讓我們把原來的常規接近上述兩者的差異是顯而易見的:

g.v(1).out.loop(1){true}{it.object.someProperty=="emitIfThis"} 

我們從上面的代碼一行來到近一個十幾對什麼是否則很簡單的遍歷。 Gremlin Java在TinkerPop3中得到了自己的貢獻,給出了lambda表達式,並對語言本身進行了重大改進,但這些先前版本生成的Java代碼實際上不值得在Groovy使事情變得非常整齊時生成或維護。