2017-01-09 8 views
0

現在、TRANVERSAL機能をarangoDB 2からarangoDB 3に移行しています。aqlには、カスタムAQL関数(より具体的なフィルタリング用)を備えたカスタムリーフ訪問者とfilterVerticesオプションがあります。ArangoDB 2.8からArangoDB 3へのfilterVertice UDFの移行

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のフィルタケースに翻訳することが除外されるがありますか?私は、UDFを使用する場合
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} 

は、パフォーマンスに影響されるようで、それらを手動で(フィルターを)LETのPARAMに結果を渡し、除外しますか?

答えて

2

は、一般的に、オプティマイザは、任意のより長い経路が特定の条件を満たしていないことを認識してここにあなたがpathオブジェクトに基づいてフィルタを書くとき、あなたが(あなたのケースpに)"prune", "exclude"に を決めることができます話します。ここ 例は、第二エッジタイプFOOを持っていない時はいつでも

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

まず整理します。 label != BAR など 特定の深度チェックまたはグローバルチェックALL,NONEANYのみがオプティマイザによって認識される場合は、2番目のものがプルーニングされます。

、あなたのケースvdで、vertexまたはedge出力にフィルタを定義する場合は、"exclude"を決定することができます

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

タイプ「BAR」を持っているすべてのエッジを除外します第一、第二名前が「BAZ」の頂点のみが含まれます。どちらの場合も、トラバーサルは継続します。

今はPRUNE, INCLUDEと言うオプションはありません。

フィルタリングのみを実装するためにUDFを使用すると、パフォーマンスが著しく低下します。これは、UDFがAQLの「ブラックボックス」であり、特に、プルーニングのためにトラバーサルに最適化できないためです。 AQLトラバーサルのパフォーマンスは、私たちの内部テストではまだまだ向上しています。そのため、私たちはそのように進むことに決めました。

残念ながら、UDF関数はAQLよりわずかに柔軟性があるため、FILTER文には変換できない関数もあります。 しかし、トラバーサル全体をユーザー定義関数として定義するだけで、3.0以前と同じ方法でトラバーサルを実行するオプションがあります。これは以前と同じパフォーマンスを持つはずです(高レベルのアルゴリズムは同じですが、ここではパフォーマンス上の影響がある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