2014-10-02 7 views
3

특정 노드에서 시작하고 끝나는 모든 경로를 찾으려합니다. 한 경로의 각 노드가 한 번만 나타납니다. 예를 들어Cypher : 반복되지 않는 단일 노드의 모든 체인을 찾는 방법은 무엇입니까?

,이 같은 그래프 : grafically

(a)-[:REL]->(b)-[:REL]->(c)-[:REL]->(a) 
(a)-[:REL]->(e)-[:REL]->(f)-[:REL]->(a) 
(e)-[:REL]->(b) 

:

e → b 
↙ ↖ ↗ ↘ 
f → a ← c 

사이퍼 코드 :

CREATE (a { name:'A' })-[:REL]->(b {name:'B'})-[:REL]->(c { name:'C' }) 
     -[:REL]->(a)-[:REL]->(e {name:'E'})-[:REL]->(f {name:'F'})-[:REL]->(a), 
     (e)-[:REL]->(b) 

내가 체인의 조사에서 시작하는 것을 좋아하는 것 (a)는

을 반환합니다.

는 노드를 통해 두 번 통과하기 때문에 (F)를 반환 만

(f)->(a)->(e)->(f) 

및 NOT

(f)->(a)->(b)->(c)->(a)->(e)->(f) 

에서 시작하면서 (a).

나는 tryied :

MATCH p=(a {name:'F'})-[:REL*1..]->(a) 
WHERE SINGLE(e1 IN TAIL(NODES(p)) WHERE SINGLE(e2 IN TAIL(NODES(p)) WHERE e1=e2)) 
RETURN p 

하지만 난 어떤 결과가있어. 내가 도달 할 수 있었던 가장이 쿼리와 시작에 불과 노드의 더 반복이없는 것입니다 :

MATCH p=(a {name:'F'})-[:REL*1..]->(a) 
WHERE SINGLE(e IN TAIL(NODES(p)) WHERE e=a) 
RETURN p 

을하지만, 분명히 그것은 또한

(f)->(a)->(b)->(c)->(a)->(e)->(f) 

을 반환하기 때문에 내가 원하는 게 아니에요 그 노드 (a)를 두 번 포함하는 경로입니다.

누군가 내게 해결책을 제안 할 수 있습니까?

미리 감사드립니다.

P. 내가 사용하는 Neo4j의 버전은 그래서 여기에 2.0

+0

이전에이 답변을 보았습니까? http://stackoverflow.com/questions/13767748/returning-only-simple-paths-in-neo4j-cypher-query 여전히 유일한 방법 일 수 있으며 필요할 수 있습니다. @FrobberOfBits 답을 함께 사용하려면 Cypher를 사용해야합니까? – JohnMark13

+0

좋은 충고, 친구. 아래 [@ JohnMark13] (http://stackoverflow.com/users/2477669/johnmark13)는 코드를 직접 알려주었습니다. 감사합니다. – mdalp

답변

2

는 :

MATCH (a { name:'A' }) 
MATCH (a)-[p:REL]->(s) 
WITH a, s 
MATCH p = s-[r:REL*]->a 
WITH [a] + nodes(p) AS ns 
    WHERE ALL (n IN ns 
     WHERE 1=LENGTH(FILTER(m IN TAIL(ns) 
          WHERE m = n))) 
RETURN ns 

이 초기 단계를 수행 한 후 마이클 링크 된 쿼리에 필터를 수행 할 @FrobberOfBits에서 아이디어를 활용 경로. 의 일부를 복잡하거나 적어도 약간 하드 읽을 수있는

MATCH (a { name:'A' }) 
MATCH (a)-[p:REL]->(s) 
WITH a, s 
MATCH p = s-[r:REL*]->a 
WITH a, nodes(p) AS ns 
WHERE ALL (n IN ns 
     WHERE 1=LENGTH(FILTER(m IN ns 
          WHERE m = n))) 
RETURN [a] + ns 

:

WITH [a] + nodes(p) AS ns  

이 어쩌면 쿼리를 만들 것이다 : 나는 당신이 또한 탈락하면 TAIL은 생략 할 수 있다고 가정 질의는 FILTER과 조합 된 ALL이며 ns의 모든 값에 대해 "기본적으로"입니다. (WHERE ALL (n in ns)은 배열의 다른 모든 값과 비교하여 발생 횟수를 계산하고 (결과적으로 결과 배열에 결과가 필터링되지 않으면 결과를 완전히 필터링합니다. 단일 요소 (1=LENGTH).

예를 콘솔 here에 추가했습니다.

+0

위대한 직업은 그것이 내가 원하는 것을 정확하게합니다. 대단히 감사합니다. – mdalp

+1

노드를 더 빨리 만들기 위해 레이블을 추가하는 것을 잊지 마십시오! –

+0

감사합니다 @MichaelHunger는 내가 게으르다는 것을 알고 놀랬습니다. – JohnMark13

2

당신의 예를 복사 조롱 일부 데이터입니다 :

$ create (a:T {label:"A"})-[:REL]->(b:T)-[:REL]->(c:T)-[:REL]->(a); 
+-------------------+ 
| No data returned. | 
+-------------------+ 
Nodes created: 3 
Relationships created: 3 
Properties set: 1 
Labels added: 3 
20 ms 
neo4j-sh (?)$ match (a:T {label:"A"})           
> CREATE a-[:REL]->(e:T)-[:REL]->(f:T)-[:REL]->(a); 
+-------------------+ 
| No data returned. | 
+-------------------+ 
Nodes created: 2 
Relationships created: 3 
Labels added: 2 
27 ms 

지금 여기 (하지만 약간의 설명이 필요)가 당신을 얻을 것이다 쿼리입니다.

match (a:T {label: "A"})-[:REL]->(somethingElse), 
     p=shortestPath((somethingElse)-[:REL*]->(a)) 
return p; 

좋아요. 근본적으로 당신은 (a)에서 (a)까지의 최단 경로를 원한다고 생각합니다. 그러나 그것은 노드에서 자신까지의 최단 경로가 항상 길이 0 인 빈 경로이기 때문에 까다 롭습니다. 따라서 shortestPath((a)-[:REL*]->(a))과 같은 작업을하면 결과는 항상 비어있는 상태가되어 원하는 내용이 아닌 것입니다.

그래서 대신에, 나는 다음 항목 (somethingElse) 한 :REL 홉에서 일치하고 원래를 실종 것을 제외하고 그 결과 반환 경로 p가 정확히 원하는 경로입니다 A.에 그 뒷면에서 최단 경로를했다 hop from a-->somethingElse.추가 홉을 감안할 때 a-->somethingElsep의 조합이 원하는 답일 것입니다. 내가 가지고 올 전에 온 사람들의 어깨에

+1

ShortestPath를 사용하는 것이 좋지만 반복이없는 가장 짧은 경로보다 길어진 경로는 모두 생략합니다. 위의 예제를 다른 관계 (e) - [: REL] -> (b)로 심오하게 만들었습니다.이 경우 (a)부터 시작하여 경로 (a) -> (e) → (b) → (c) → (a). – mdalp

+2

@FrobberOfBits 이유가 무엇이든, 나는 이것을 결코 생각하지 못했습니다. 나는 이제 조금 더 똑똑한 그래프이다. – JohnMark13