2016-08-01 3 views
1

처럼 보이는 neo4j의 그래프가 있습니다. 나는 그것을 this과 같은 것으로 만들고 싶습니다.Neo4j : 하위를 탐색하고 속성을 기반으로 어린이들 간의 순서 관계를 만듭니다.

일반화 된 문제 :

어떻게 (날짜 별, 예를 들어 순서) 특정 순서로 자녀를 통과하고 주어진 순서대로 자녀 사이의 관계를 만들려면 어떻게해야합니까?

특정 문제 :

각 : (: 진단) 노드 및 다중 (: 진단) 노드가 동일한 공유 할 수 있습니다 (: 개념) (사람) 여러가있을 수 있습니다. "조건"으로 표시된 노드는 (: 개념) 노드입니다. (: 진단) 노드는 사람에 대한 진단 발생을 나타내므로 두 사람이 (진단) 노드를 공유하지 않습니다. 그러나 여러 사람이 동일한 종류의 진단으로 진단 될 수 있으며 진단 유형 (예 : 2 형 당뇨병, 동맥류 등)은 (: 개념) 노드로 설명됩니다.

(: Diagnosis) 노드의 시간 순서에 따라 (: Concept) 노드 간의 관계 경로를 만들고 각 (: Concept)가 처음 진단되었을 때만 포함하고 싶습니다.

지금까지 내가 만든 한 새 사이의 관계 (: 사람)과이 같은 (개념) : 나는 하나의 물건을 테스트했습니다

(:Person {person_id: <some_number>})-[:DIAGNOSED_WITH {start_date: yyyy/mm/dd}]->(:Concept) 

(: 사람). 나는 다음과 같은 사이퍼 쿼리 이런 짓을 : 관계 : [DIAGNOSED_WITH]의 시작 날짜를 기준으로 (개념) 노드

match (p:Person {person_id: "12345"})--(c:ConditionOccurrence)--(con:Concept) WITH 
    p.person_id as people, con.concept_id as concepts, min(c.condition_start_date) as 
    start_date ORDER BY start_date, concepts 
MATCH (p1:Person {person_id: people}) 
MATCH (c2:Concept {concept_id: concepts}) 
MERGE (p1)-[:DIAGNOSED_WITH {start_date: start_date}]->(c2) 

가 지금은 사이의 관계를 만들려고합니다. 그것은 다음과 같이 보일 것이다 : [: DIAGNOSED_WITH] 주어진에 대한 관계

(concept 1)-[:NEXT {person_id: #}]->(concept 2)-[:NEXT {person_id: #})]->(concept 3)... 

나는 모든 모음에 UNWIND를 사용하여 시도 (: 사람)하지만 난 꽤 WITH와 방법 UNWIND 작품을 이해 생각하지 않습니다. 내가 통해 갈 곳

match (p:Person {person_id: "12345"})-[d:DIAGNOSED_WITH]->(c:Concept) WITH 
    p.person_id AS person_id, d AS diagnoses ORDER BY d.start_date 
WITH collect(diagnoses) as ordered_diagnoses, person_id as person_id 
UNWIND ordered_diagnoses as diagnosis 
MATCH (:Person {person_id: person_id})-[diagnosis]->(c1:Concept) 
MATCH (:Person {person_id: person_id})-[d2:DIAGNOSED_WITH]->(c2:Concept) WHERE 
    d2.start_date >= diagnosis.start_date AND d2 <> diagnosis 
WITH min(d2.start_date) AS min_start_date2, diagnosis, person_id, c1 
MATCH (:Person {person_id: person_id})-[:DIAGNOSED_WITH {start_date: 
    min_start_date2}]->(c2:Concept) 
MERGE (c1)-[:NEXT {person_id: person_id, start_date1: diagnosis.start_date, 
    start_date2: min_start_date2}]->(c2) 

나는 또한 "터치"접근을 시도 : (: 개념) 진단이 동일한 날짜에 시작에 만들어진 노드

다음 쿼리는 모든 사이의 관계를 그려 보인다

match (p:Person {person_id: "2851389"})-[d:DIAGNOSED_WITH]->(c:Concept) WITH 
    p.person_id AS person_id, d AS diagnoses ORDER BY d.start_date 
WITH collect(diagnoses) as ordered_diagnoses, person_id as person_id 
UNWIND ordered_diagnoses as diagnosis 
MATCH (:Person {person_id: person_id})-[diagnosis]->(c1:Concept) 
SET diagnosis.touched = TRUE 
WITH person_id, c1, diagnosis 
MATCH (:Person {person_id: person_id})-[d2:DIAGNOSED_WITH {touched: FALSE}]-> 
    (c2:Concept) WHERE d2.start_date >= diagnosis.start_date 
SET d2.touched = TRUE 
WITH min(d2.start_date) as min_start_date2, person_id, c1, diagnosis 
MATCH (:Person {person_id: person_id})-[:DIAGNOSED_WITH {start_date: 
    min_start_date2}]->(c2:Concept) 
MERGE (c1)-[:NEXT {person_id: person_id, start_date1: diagnosis.start_date, 
    start_date2: min_start_date2}]->(c2) 

이 도와주세요 : 관계와 이미 발생한 터치 것들,하지만 코드는 나도 인해 UNWINDWITH의 이해 나의 부족에 원하는 방식으로 작동하지 않습니다! 감사!

답변

1

저는 사이퍼에서 해킹을 중단하기로 결정했고 py2neo 패키지로 파이썬에서 그랬습니다. 훨씬 더 간단합니다. 여기에 관심이 경우 코드는 다음과 같습니다

#!/usr/bin/env python 

from py2neo import authenticate, Graph 
from py2neo import Node, Relationship 

authenticate("localhost:7474", "neo4j", "neo3j") 
# default uri for local Neo4j instance 
graphdb = Graph('http://localhost:7474/db/data') 

def set_NEXT_rels(person_id): 
    concepts = graphdb.run("MATCH (p:Person {person_id: \""+person_id+"\"})-[d:DIAGNOSED_WITH]->(c:Concept) RETURN c.concept_id, d.start_date ORDER BY d.start_date, c.concept_name").data() 
    for i in range(0, len(concepts)-1): 
     d = graphdb.run("MATCH (p:Person {person_id: \""+person_id+"\"})-[d1:DIAGNOSED_WITH {start_date: \""+concepts[i]['d.start_date']+"\"}]->(c1:Concept {concept_id: \""+concepts[i]['c.concept_id']+"\"}) MATCH (p:Person {person_id: \""+person_id+"\"})-[d2:DIAGNOSED_WITH {start_date: \""+concepts[i+1]['d.start_date']+"\"}]->(c2:Concept {concept_id: \""+concepts[i+1]['c.concept_id']+"\"}) MERGE (c1)-[:NEXT {person_id: \""+person_id+"\", start_date_d1: d1.start_date, start_date_d2: d2.start_date}]->(c2)").data() 

def process_conditions_by_person(): 
    people = graphdb.run("MATCH (p:Person) RETURN p.person_id").data() 
    for person in people: 
     set_NEXT_rels(person['p.person_id']) 

def main(): 
    process_conditions_by_person() 

if __name__ == "__main__": 
    main() 
1

APOC Procedures library 여기에 당신을 도울 수있는 뭔가가. 특히 헬퍼 섹션의 콜렉션 함수 하위 섹션에는 목록을 가져와 하위 목록 쌍의 목록을 출력하는 절차 apoc.coll.pairs([list])이 있습니다.마지막 쌍은 목록의 마지막 요소가 null과 쌍이 될 것이므로 노드를 연결하는 것이 목표 인 경우이를 삭제해야합니다. 여기

는 사용의 예 :

WITH [1, 2, 3, 4, 5] AS stuff 
CALL apoc.coll.pairs(stuff) YIELD value 
WITH value[0..size(value)-1] AS numbers 
RETURN numbers 

이 출력됩니다 : 노드를 연결하려면이 옵션을 사용하여 측면에서 그래서 [[1, 2], [2, 3], [3, 4], [4, 5]]

, 당신은 당신이 관심있는 노드에 대한 쿼리 검색을 만들 것 필요에 따라 정렬하고 목록에 COLLECT()하여 쌍() APOC 절차를 호출 한 다음 FOREACH를 사용하여 각 쌍 사이의 관계를 만듭니다.

편집

내 대답부터 APOC에 일부 변경 :.

1) apoc.coll.pairs() 당신은 인라인 사용할 수 있습니다, 지금은 기능이 아닌 절차 (CALL 또는 수율을 사용할 필요가 없습니다입니다

2) apoc.nodes.link()은 노드 모음을 가져 와서 주어진 유형의 관계를 생성하는 절차이므로 (일반적으로 foreach에서 관계를 만들지 않아도 됨) 일반적으로 노드를 연결하는 기본 방법입니다.

관련 문제