Cypher 기본 쿼리
Cypher 기본 쿼리
Cypher로 그래프를 다룰 때 가장 먼저 익혀야 할 건 "어떤 패턴을 찾아서 무엇을 돌려받을지"를 적는 방식이에요. 이 페이지에서는 MATCH·RETURN 같은 핵심 절로 데이터 모델을 만들고, 노드를 찾고, 연결된 노드와 경로를 탐색하는 기본기를 차근차근 보여 드릴게요. 영화 데이터 모델을 예로 들어 함께 따라 하면 금방 감을 잡을 수 있을 거예요.
데이터 모델 만들기
property graph 데이터베이스를 만들기 전에 적절한 데이터 모델을 설계하는 게 중요해요. 모델이 그래프에 구조를 부여하고, 사용자가 원하는 정보를 효율적으로 찾게 해 주니까요.
Neo4j 영화 데이터 모델은 이렇게 생겼어요.
Person노드 — 프로퍼티name,bornMovie노드 — 프로퍼티title,released,taglinePerson과Movie사이의 관계 타입 5가지 —ACTED_IN,DIRECTED,PRODUCED,WROTE,REVIEWED- 관계 타입 중 두 가지는 프로퍼티를 가져요.
ACTED_IN은roles,REVIEWED는summary와rating이요.
노드 찾기
MATCH 절은 그래프에서 특정 패턴(예: 특정 노드)을 찾는 데 쓰고, RETURN 절은 찾은 패턴 중 무엇을 돌려줄지를 정해요. 라벨이 Person이고 이름이 Keanu Reeves인 노드를 찾아 name과 born을 돌려받는 쿼리는 이래요.
MATCH (keanu:Person {name:'Keanu Reeves'})
RETURN keanu.name AS name, keanu.born AS born
여러 노드를 한 번에 찾을 수도 있어요. 모든 Person 노드를 매칭하고 결과를 5행으로 제한하면 이렇죠.
MATCH (people:Person)
RETURN people
LIMIT 5
절의 조합 방식
SQL과 비슷하게, Cypher 쿼리는 여러 절을 이어 붙여 구성돼요. 각 절은 그래프의 상태와 중간 결과 테이블을 입력으로 받아 처리한 뒤, 갱신된 상태와 결과를 다음 절로 넘겨줘요. 첫 절은 쿼리 시작 전의 그래프 상태와 빈 중간 결과를 입력받고, 마지막 절의 출력이 곧 쿼리 결과가 돼요.
이때 어떤 절이 빈 중간 결과 테이블을 돌려주면 다음 절로 넘겨줄 것이 없어져서 쿼리가 끝나요. 이런 동작을 우회하려면 MATCH를 OPTIONAL MATCH로 바꾸는 방법을 쓸 수 있어요.
아래 예시는 첫 MATCH에서 Person 노드를 모두 찾고, 다음 절에서 1980년대에 태어난 Person만 걸러낸 뒤, 최종 절에서 출생 연도 내림차순으로 결과를 돌려줘요.
MATCH (bornInEighties:Person)
WHERE bornInEighties.born >= 1980 AND bornInEighties.born < 1990
RETURN bornInEighties.name as name, bornInEighties.born as born
ORDER BY born DESC
연결된 노드 찾기
노드끼리 어떻게 연결되어 있는지 알아보려면 쿼리에 관계를 추가해야 해요. 쿼리에서 관계 타입·프로퍼티·방향, 그리고 패턴의 시작·끝 노드를 지정할 수 있죠.
영화 The Matrix의 감독을 찾아 그 이름을 돌려주는 쿼리는 이렇게 돼요.
MATCH (m:Movie {title: 'The Matrix'})<-[d:DIRECTED]-(p:Person)
RETURN p.name as director
노드를 연결하는 관계의 타입이 무엇인지도 볼 수 있어요. Tom Hanks 노드에서 Movie 노드로 나가는 관계들을 찾아 각 관계의 타입과 연결된 영화 제목을 돌려주는 쿼리예요.
MATCH (tom:Person {name:'Tom Hanks'})-[r]->(m:Movie)
RETURN type(r) AS type, m.title AS movie
Cypher는 클로즈에 라벨 표현식을 붙여 쿼리를 더 다듬을 수 있어요. 아래는 NOT 라벨 표현식(!)을 써서 Tom Hanks에 연결된 관계 중 타입이 ACTED_IN이 아닌 것을 돌려줘요.
MATCH (:Person {name:'Tom Hanks'})-[r:!ACTED_IN]->(m:Movie)
RETURN type(r) AS type, m.title AS movies
경로 찾기
노드 사이의 경로를 찾는 데는 여러 방법이 있어요. 고정 길이 패턴은 정량자({n})로 노드 사이 거리(홉 수)를 지정해서 찾아요. 아래는 Tom Hanks로부터 정확히 2홉 떨어진 Person 노드를 찾고 처음 5행을 돌려주는 쿼리예요. DISTINCT 연산자는 결과에 중복이 없게 해 줘요.
MATCH (tom:Person {name:'Tom Hanks'})--{2}(colleagues:Person)
RETURN DISTINCT colleagues.name AS name, colleagues.born AS bornIn
ORDER BY bornIn
LIMIT 5
가변 길이 패턴으로 1홉에서 4홉 사이의 Person 노드를 찾을 수도 있어요.
MATCH (p:Person {name:'Tom Hanks'})--{1,4}(colleagues:Person)
RETURN DISTINCT colleagues.name AS name, colleagues.born AS bornIn
ORDER BY bornIn, name
LIMIT 5
SHORTEST 키워드는 두 노드 사이의 최단 경로 변형을 찾는 데 써요. 아래 예시는 Keanu Reeves와 Tom Cruise 사이의 ALL SHORTEST 경로를 모두 찾아 그 개수와 길이를 계산해요.
MATCH p = ALL SHORTEST (:Person {name:"Keanu Reeves"})--+(:Person {name:"Tom Cruise"})
RETURN count(p) AS pathCount, length(p) AS pathLength
추천 찾기
Cypher는 더 복잡한 쿼리도 만들 수 있어요. 아래 쿼리는 Keanu Reeves가 아직 함께 일한 적은 없지만 그의 공동 출연 배우들이 함께 일한 배우(코-코-배우)를 추천하고, 추천 강도순으로 정렬해요.
MATCH (keanu:Person {name:'Keanu Reeves'})-[:ACTED_IN]->(m:Movie)<-[:ACTED_IN]-(coActors:Person),
(coActors:Person)-[:ACTED_IN]->(m2:Movie)<-[:ACTED_IN]-(cocoActors:Person)
WHERE NOT (keanu)-[:ACTED_IN]->()<-[:ACTED_IN]-(cocoActors) AND keanu <> cocoActors
RETURN cocoActors.name AS recommended, count(cocoActors) AS strength
ORDER BY strength DESC
LIMIT 7
그래프 지우기
그래프의 모든 노드와 관계를 지우려면 다음 쿼리를 실행하면 돼요. DETACH DELETE는 관계까지 함께 제거해 줘요.
MATCH (n)
DETACH DELETE n