2017-01-09 30 views
0

我目前正在將arangoDB 2的TRAVERSAL函數遷移到arangoDB 3.aql有一個自定義葉子訪問器和一個filterVertices選項以及一個自定義AQL函數(用於更具體的過濾)。從ArangoDB 2.8遷移過濾器Vertice UDF到ArangoDB 3

FOR result IN TRAVERSAL(
    page, 
    menu, 
    "page/99999999999999", 
    "inbound", 
    {filterVertices : "udf::customFilter", visitor : "udf::customVisitor", } 
) RETURN result 

葉遊客UDF相對容易轉移,因爲它僅僅是創建一個自定義對象,但我有自阿朗戈3圖表功能已被刪除與filterVertices UDF麻煩。

有一些情況下,像在filterVertices UDF

//check the page status 
    if (mismatch == 1) { 
     //stop traversal and not return mismatched 
     return ['exclude', 'prune']; 
    } else if (mismatch == 2) { 
     //stop but return mismatched 
     return 'prune'; 
    } else { 
     //exclude mismatched but continue 
     return 'exclude'; 
    } 

我的問題下面是一個應該如何剪枝,並排除被過濾器的情況恰好低於AQL翻譯?

FOR v, d, p IN 1..10 INBOUND "page/99999999999999" menu 
    LET filtered = CALL('udf::customFilter',v,p) 
    LET result = CALL('udf::customVisitor',v,d,p) 
RETURN {filtered:filtered,result:result} 

請問如果我使用UDF的性能受到影響是手動傳遞導致LET PARAM和排除(過濾器)呢?

回答

2

一般來說,你可以在"prune", "exclude"決定,當你寫基於path對象上的過濾器(在你的情況p) 這裏優化器將認識到,任何更長的路徑無法滿足一定的條件。這裏 的例子是:

FILTER p.edges[1].type == 'FOO' 
FILTER p.edges[*].label ALL == 'BAR' 
FILTER p.vertices[*].age ALL >= 18 

首先會修剪每當第二邊緣沒有類型FOO。 每當它發現一個label != BAR 等 只有特定深度支票或全球檢查ALLNONEANY可以被優化器識別的第二會修剪。

您可以在"exclude"決定,如果你定義在vertexedge輸出過濾器,你的情況vd

FILTER d.type != "BAR" 
FILTER v.name == "BAZ" 

第一個將排除有型「BAR」所有邊緣,第二將只包含名稱爲「BAZ」的頂點。在這兩種情況下,遍歷都會繼續。

現在沒有選擇可以說PRUNE, INCLUDE

僅使用UDF來實現過濾對性能而言極其糟糕。這是因爲UDF對於AQL來說是一個「黑盒子」,特​​別是不能在遍歷中進行修剪優化。 在我們的內部測試中,AQL遍歷的性能還是好幾個數量級,這就是我們決定這樣做的原因。

不幸的是,UDF函數比AQL稍微靈活一點,所以可能有一些函數不能翻譯成FILTER only語句。 但是仍然有一個選項可以像以前的3.0一樣執行這些遍歷,只需將整個Traversal定義爲用戶定義的函數即可。這應該具有和以前一樣的性能(高級算法是相同的,但是我們在3.0中改變了許多其他內部部件,這些部件在這裏具有性能副作用)。

這在這裏更詳細地解釋: https://docs.arangodb.com/3.1/Manual/Graphs/Traversals/UsingTraversalObjects.html

,而新的UDF應該大致是這樣的,並採取startVertex輸入:

var db = require("internal").db; 
var traversal = require("@arangodb/graph/traversal"); 
var config = { 
    datasource: traversal.collectionDatasource("menu"), 
    filter: db._aqlfunctions.document("UDF::CUSTOMFILTER").code, 
    visitor: db._aqlfunctions.document("UDF::CUSTOMVISITOR").code, 
    maxDepth: 1 // has to be defined 
}; 
var result = { 
    visited: { 
    vertices: [ ], 
    paths: [ ] 
    } 
}; 
var traverser = new traversal.Traverser(config); 
traverser.traverse(result, startVertex); 
[...] // Do stuff with result here 

如果你需要一些幫助,從UDF翻譯到FILTER或者讓遍歷UDF正常運行,請通過https://groups.google.com/forum/#!forum/arangodb直接與我們聯繫。我們可能需要一些郵件來整理你需要的所有細節。

+0

太有意思了!我期待着這樣的答案。我只需要確定我沒有錯過文檔中的任何內容。 不幸的是,我的函數依賴於用戶輸入和收集結果,因此我不太確定在FILTER語句中將其全部轉換是多麼可行,但是我明白了你的意思,並且我將繼續爲下一輪重構。 我知道它很長,但如果你設法在AQL中包含「if」語句,它會增加大量的靈活性! 我正在使用isDeterministic選項來爲將來的更新做好準備。 – GeorgeKaf