2016-10-15 6 views
1

ループのないノード間のすべての可能なパスを取得するのに問題があります。私はneo4j 3.0.4を使用します。私は例を用意しましたが、まず短い説明がありました。私はAからZまでのノードを持っています。これらのノードはそれぞれの方法で接続できます。私はループなしですべての可能なパスを取得したい、特定のノードが複数回訪問されていないことを意味します。ここでCypher:ループのないすべてのパス

例:

CREATE (newNode {name:'A'}) 
RETURN newNode; 

CREATE (newNode {name:'B'}) 
RETURN newNode; 

CREATE (newNode {name:'C'}) 
RETURN newNode; 

CREATE (newNode {name:'D'}) 
RETURN newNode; 

CREATE (newNode {name:'E'}) 
RETURN newNode; 

CREATE (newNode {name:'Z'}) 
RETURN newNode; 


MATCH (n1), (n2) 
WHERE n1.name = 'A' AND n2.name = 'B' 
CREATE 
    (n1)-[r:CONNECTED_TO]->(n2) 
RETURN n1, n2, r; 

MATCH (n1), (n2) 
WHERE n1.name = 'A' AND n2.name = 'C' 
CREATE 
    (n1)-[r:CONNECTED_TO]->(n2) 
RETURN n1, n2, r; 

MATCH (n1), (n2) 
WHERE n1.name = 'B' AND n2.name = 'C' 
CREATE 
    (n1)-[r:CONNECTED_TO]->(n2) 
RETURN n1, n2, r; 

MATCH (n1), (n2) 
WHERE n1.name = 'C' AND n2.name = 'D' 
CREATE 
    (n1)-[r:CONNECTED_TO]->(n2) 
RETURN n1, n2, r; 

MATCH (n1), (n2) 
WHERE n1.name = 'D' AND n2.name = 'E' 
CREATE 
    (n1)-[r:CONNECTED_TO]->(n2) 
RETURN n1, n2, r; 

MATCH (n1), (n2) 
WHERE n1.name = 'E' AND n2.name = 'Z' 
CREATE 
    (n1)-[r:CONNECTED_TO]->(n2) 
RETURN n1, n2, r; 

MATCH (n1), (n2) 
WHERE n1.name = 'D' AND n2.name = 'Z' 
CREATE 
    (n1)-[r:CONNECTED_TO]->(n2) 
RETURN n1, n2, r; 

MATCH (n1), (n2) 
WHERE n1.name = 'D' AND n2.name = 'A' 
CREATE 
    (n1)-[r:CONNECTED_TO]->(n2) 
RETURN n1, n2, r; 

MATCH (n1), (n2) 
WHERE n1.name = 'B' AND n2.name = 'A' 
CREATE 
    (n1)-[r:CONNECTED_TO]->(n2) 
RETURN n1, n2, r; 


MATCH p=(from{name:'A'}), (to{name:'Z'}), 
path = (from)-[r*]->(to) 
RETURN path 

私は最後のクエリを実行する場合、私はまた、A-> B-> A-> C-> D-> Zのようなパスを取得します。私はこのループA→B→Aを避けたい。 allShortestPathsは、ほんの少しのホップだけでパスを提供するため、私にとっては機能しません。しかし、私はループなしですべてのパスを取得したい、ホップの数は関係ありません。クエリが非常に高価であるため、結果またはパスの長さを制限する必要があります。

path = (from)-[r*20]->(to) 

しかし、これはショートパスでも発生する可能性があるため、ループを回避する方法ではありません。

EDIT1: [OK]を、今私は、このための可能な解決策を考え出す:

MATCH (from{name:'A'}), (to{name:'Z'}), 
path = (from)-[:CONNECTED_TO*]->(to) 
WHERE NONE (n IN NODES(path) WHERE SIZE(FILTER(x IN NODES(path) WHERE n = x))> 1) 
RETURN path, LENGTH(path) as length 
ORDER BY length; 

このクエリは、動作しているようですが、私はそれが非常に高価であることを前提としています。誰かがより良いソリューションを提供できるか?

WHERE ALL(x IN NODES(path) WHERE SINGLE(y IN NODES(path) WHERE y = x)) 

をしかし、私はあなたが基本的に、より効率的な方法を見つけることができます信じていません:あなたはこのように変更した場合

答えて

5

あなたのフィルタが速く、わずかに出て失敗します。質問に「すべてのパス」という単語が含まれていて、サンプルに無限の関係がある場合、通常はオプションがかなり制限されています:)

+0

Hmm、ok。私はこれを試して、それは動作します。とにかくありがとうございました! :) – Stefan

+2

Btwは 'apoc'に慣れているので、ユーザ定義関数でリリース3.1よりはるかに簡単になるでしょう:フィルタは' WHERE size(apoc.coll.toSet(NODES(path) ))= size(NODES(path)) 'である。 [history](http://stackoverflow.com/questions/13767748/returning-only-simple-paths-in-neo4j-cypher-query)を振り返ってみると、それは難しい問題だとわかるでしょうが、間違いなくより良い。 –

関連する問題