2017-11-22 9 views
0

私は何百万というノードとリレーションを持つグラフを持っています。私は2つのノード間のすべてのパスを取得する必要があります。私の場合、関連パスのノードはすべてと同じラベルでなければなりません。2つのノード間のすべてのパスのCypher

match (n:Label) match (m:Label) where n.NAME='foo' and m.NAME='foo2' 
match p=(n)-[r*..20]-(m) where all(x in nodes(p) where (x:Label)) 
with p 
return p, EXTRACT(x IN nodes(p) | x.NAME), EXTRACT(r IN relationships(p) | type(r)) 

ノードラベルでカウント「ラベルは、」私の「どこのすべて」句でパスを削減しようと、2つのノードとの間のすべての可能なパスを見つけるために、すべてのグラフでは、約20しかし、このクエリのトラバースです。それは私のdbをクラッシュします。

ラベル名「ラベル」とその関係を持つすべてのノードを取得し、コストを削減するためにサブグラフ間のパスを照会する必要があります。

+2

これは計算が難しいクエリです。 REL_TYPE1 | REL_TYPE2'(可能な関係タイプを列挙する)を 'MATCH'に入れます。2. APOCライブラリの[パスエキスパンダー](https://neo4j-contrib.github.io/neo4j-apoc-procedures/#_path_expander)。 –

答えて

0

多くの場合、パスを生成するときにラベルフィルタを指定できるので、役立つはずのPath Expander APOC手順があります。例えば

MATCH (n:Label {NAME: 'foo'}) 
WITH COLLECT(n) AS ns1 
MATCH (m:Label {NAME: 'foo2'}) 
WITH ns1 + COLLECT(m) AS startNodes 
CALL apoc.path.expandConfig(
    startNodes, 
    {labelFilter: '+Label', minLevel: 1, maxLevel: 20} 
) YIELD path 
RETURN 
    path, 
    [x IN nodes(path) | x.NAME] AS names, 
    [r IN relationships(path) | TYPE(r)] AS types; 
0

ノードの数百万のグラフ(20の長さまでも)メモリのオーバーフローを引き起こす可能性があるすべての可能な経路を見つけることを試みます。

あなたができることは、より小さなセグメントに分割することです。クエリはエレガントではありませんが、うまくいくはずです。

我々は一度に5の経路長をしている場合たとえば、2セグメントのクエリは次のようになります。

MATCH p1 = (n1:Label)-[r1*..5]-(n2:Label), p2 = (n2:Label)-[r2*..5]-(n3:Label) 
WHERE all(x1 in nodes(p1) WHERE (x1:Label)) 
AND all(x2 in nodes(p2) WHERE (x2:Label)) 
RETURN r1, r2 

このクエリのコストプランがそうのようになります。

+-----------------------+----------------------+---------------------+ 
| Operator    | Variables   | Other    | 
+-----------------------+----------------------+---------------------+ 
| +ProduceResults  | r1     | r1     | 
| |      +----------------------+---------------------+ 
| +Filter    | n1, n2, n3, r1, r2 | [see below]   | 
| |      +----------------------+---------------------+ 
| +VarLengthExpand(All) | n1, r1 -- n2, n3, r2 | (n2)-[r1:*..5]-(n1) | 
| |      +----------------------+---------------------+ 
| +Filter    | n2, n3, r2   | n3:Label   | 
| |      +----------------------+---------------------+ 
| +VarLengthExpand(All) | n3, r2 -- n2   | (n2)-[r2:*..5]-(n3) | 
| |      +----------------------+---------------------+ 
| +NodeByLabelScan  | n2     | :Label    | 
+-----------------------+----------------------+---------------------+ 

最初の展開の直後に、フィルタが開始されずに終了するファイルが:Labelでフィルタリングされ、次に2番目の展開が行われることがわかります。

あなたのNeoバージョンが2.2以上で、p1p2will not include the same relationshipsの間です。

あなたが実際にこのフィルタリングはProduceResults演算子(第2ライン)前のフィルタで行わ見ることができます:今、あなたはまた、我々はそれだけで最後のフィルタにパス内のすべてのノードをチェックすることを確認する必要があり

all(x1 in NodesFunction(ProjectedPath(Set(r1, n1),)) where x1:Label) 
AND none(r1 in r1 where any(r2 in r2 where r1 == r2)) 
AND n1:Label 

を。したがって、このようなパス(a:Label) - (b:Blah) - (c:Label)は最初のセグメントを通過し、結果生成前にのみフィルタリングされます。

したがって、すべてのセグメントノードが:Labelになっていることを確認してさらに最適化することができます。同様の過去の関係を手動でチェックします。第2段階のみを表示:

WITH n2, r1 
MATCH p2 = (n2:Label)-[r2*..5]-(n3:Label) 
WHERE all(x2 in nodes(p2) WHERE (x2:Label)) 
AND none(r1 in r1 where any(r2 in r2 where r1 == r2)) 

私は言及を忘れましたが、そのようなクエリは怠惰な方法で実行されることを覚えておいてください。

関連する問題