2016-08-03 2 views
5

私はArangoDBに単純なノードリンクグラフを持っています。 1つの事前選択されたノードからどのようにトラバースし、それに関連するすべてのノードを返すことができますか?例えばArangoDB:選択されたノードに関連するあらゆるノードを取得します。

は: A→B、B→C、C→D、C→E、F→B、F→E

は、それらのいずれも同じ結果(それらのすべて)を返すべきである選択します。

私はArangoDBの新機能です。

答えて

9

必要なものはAQL graph traversalです.ArangoDB 2.8以降で利用可能です。古いバージョンではグラフ関連の関数群が提供されていましたが、ネイティブAQLトラバーサルはより高速で柔軟性があり、グラフ関数は3.0からは使用できなくなりました。


AQLトラバーサルは、可変頂点まで、開始頂点に接続されたエッジに従えましょう。遭遇した各頂点にアクセスすることができる。フィルタリングや結果の構築、そしてこの頂点に導かれたエッジと、頂点と端点の両方を含む最初から最後までの完全なパスが含まれます。

あなたの場合、訪問された頂点の名前のみが返される必要があります。あなたはそこに文書コレクションnodeとエッジコレクションlinksだと、彼らはこのグラフのデータが含まれていると仮定すると、以下のAQLは、問い合わせを実行することができます。

Example Graph

// follow edges ("links" collection) in outbound direction, starting at A 
FOR v IN OUTBOUND "node/A" links 
    // return the key (node name) for every vertex we see 
    RETURN v._key 

これだけトラバース深ので、[ "B" ]を返します。暗黙的に1..1(最小= 1、最大= 1)です。

FOR v IN 1..10 OUTBOUND "node/A" links 
    RETURN v._key 

これは私たち[ "B", "C", "D", "E"]を与えるだろう:私たちは最大の深さを増加させた場合、我々は間接的にも接続されているノードを含めることができます。グラフを見ると、これは正しいです:我々は、私たちが来る頂点から別の頂点(矢印の方向)を指し示す辺をたどるだけです。逆を行うために、我々はINBOUNDを使用することができますが、あなたのケースでは、我々はエッジの方向性を無視してフォローしたい:

FOR v IN 1..10 ANY "node/A" links 
    RETURN v._key 

結果は、最初は少し意外かもしれません:
[ "B", "C", "D", "E", "F", "B", "F", "E", "C", "D", "B" ]

重複したノードが返されることがあります。その理由は、例えばBからB-F-Eを経由してAからCへの複数の経路が存在し、問い合わせが変数vとして各経路の最後のノードを返すためです。 (これは実際には10の最大の深さまですべて可能なパスを処理しませんが、あなたがそうするトラバーサルオプションOPTIONS {uniqueEdges: "none"}を設定することができます。)

それは優れているかを理解するためにフォーマットされたトラバーサルパスを返すように助けることができます(つまり、ノードが到達しているか)に行く:

FOR v, e, p IN 1..10 ANY "node/A" links OPTIONS {uniqueEdges: "path"} 
    RETURN CONCAT_SEPARATOR(" - ", p.vertices[*]._key) 

結果:

[ 
    "A - B", 
    "A - B - C", 
    "A - B - C - D", 
    "A - B - C - E", 
    "A - B - C - E - F", 
    "A - B - C - E - F - B", 
    "A - B - F", 
    "A - B - F - E", 
    "A - B - F - E - C", 
    "A - B - F - E - C - D", 
    "A - B - F - E - C - B" 
] 

サイクルがグラフであるが、最大深さは後方を超えているため、無限ループがあることはできません10ホップ。しかし、上記のように、深度10に達することさえありません。(デフォルト)オプションは、パスごとに2回エッジをたどらないためです(uniqueEdges: "path")。

とにかく、これは望ましい結果ではありません。安価なやり方は、RETURN DISTINCTCOLLECTなどを使用して重複を削除することです。しかし、無限にエッジに追従しないように、トラバースオプションを調整する方が良いです。

uniqueEdges: "global"には、Bノードが2回含まれていますが、uniqueVertices: "global"には希望の結果が得られます。さらに、この場合には、幅優先探索用のbfs: trueを使用することができます。違いは、Fノードへの経路がより短いことである(A-B-C-E-Fの代わりにA-B-F)。一般的に、使用する正確なオプションは、データセットと質問に大きく依存します。

解決する問題がもう1つあります。トラバーサルに開始点(すべてのパスでp.vertices[0]以外)が含まれていません。これは簡単に0に最小深さを設定することによってArangoDB 3.0以降を使用して解くことができる:

FOR v IN 0..10 ANY "node/A" links OPTIONS {uniqueVertices: "global"} 
    RETURN v._key 

[ "A", "B", "C", "D", "E", "F" ]

からFを介してすべてのノードが、我々ができ、関係なく、開始頂点の、返されることを確認するには次のテストクエリを発行します。

FOR doc IN node 
    RETURN (
     FOR v IN 0..10 ANY doc links OPTIONS {uniqueVertices: "global"} 
      SORT v._key 
      RETURN v._key 
    ) 

すべてのサブアレイは同じに見えるはずです。ノード名をトラバーサル順序で戻す場合は、SORT操作を削除します。これが助けてくれることを願っています)

+0

すごい答えです。本当にありがとうございます。私のようなダン・アレンゴが、すべてのことを明確な方法で説明してくれたことは、本当に役に立ちます –

関連する問題