1 Cypher 기초: Neo4j 그래프 쿼리 언어
1.1 Cypher란
Cypher는 Neo4j의 그래프 쿼리 언어다. SQL이 테이블을 다루듯, Cypher는 노드와 관계를 다룬다.
핵심 철학: ASCII art로 그래프를 표현
-- SQL: 테이블 JOIN
SELECT p.name, c.name
FROM persons p JOIN companies c ON p.company_id = c.id
-- Cypher: 그래프 패턴
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
RETURN p.name, c.name1.2 기본 문법 구조
(노드) -[관계]-> (노드)
↑ ↑
레이블:속성 레이블:속성
-- 노드 표현
(n) -- 변수 n, 레이블 없음
(p:Person) -- Person 레이블
(p:Person {name: "A"}) -- Person 레이블 + 속성 필터
-- 관계 표현
-[r]- -- 방향 없음
-[r:FOUNDED]-> -- 방향 있음, FOUNDED 타입
-[r:FOUNDED {year: 2003}]-> -- 속성 포함1.3 CREATE: 노드와 관계 생성
-- 노드 생성
CREATE (p:Person {name: 'Elon Musk', born: 1971})
CREATE (c1:Company {name: 'Tesla', sector: 'EV'})
CREATE (c2:Company {name: 'SpaceX', sector: 'Aerospace'})
CREATE (loc:Location {name: 'Austin', state: 'Texas'})
-- 관계 생성 (노드 참조 필요)
MATCH (p:Person {name: 'Elon Musk'})
MATCH (c:Company {name: 'Tesla'})
CREATE (p)-[:FOUNDED {year: 2003}]->(c)
-- 노드와 관계를 한 번에 생성
CREATE (p:Person {name: 'Jeff Bezos'})
-[:FOUNDED {year: 1994}]->
(c:Company {name: 'Amazon'})1.3.1 MERGE: 없으면 생성, 있으면 그대로
-- 중복 방지 (GraphRAG에서 자주 사용)
MERGE (p:Person {name: 'Elon Musk'})
ON CREATE SET p.born = 1971, p.created_at = datetime()
ON MATCH SET p.updated_at = datetime()
RETURN p1.4 MATCH: 패턴 탐색
1.4.1 기본 패턴
1.4.2 경로 탐색 (GraphRAG 핵심)
-- 2-hop: A → B → C
MATCH (p:Person)-[:FOUNDED]->(c:Company)-[:LOCATED_IN]->(l:Location)
RETURN p.name, c.name, l.name
-- 가변 길이 경로 (Multi-hop)
MATCH (start:Person {name: 'Elon Musk'})-[:FOUNDED*1..3]->(end)
RETURN end
-- 최단 경로
MATCH path = shortestPath(
(a:Person {name: 'Elon Musk'})-[*]-(b:Company {name: 'OpenAI'})
)
RETURN path1.5 WHERE: 필터링
-- 속성 조건
MATCH (p:Person)
WHERE p.born > 1970 AND p.born < 1980
RETURN p.name, p.born
-- 문자열 조건
MATCH (c:Company)
WHERE c.name STARTS WITH 'Sp'
RETURN c.name
-- 리스트 포함 여부
MATCH (n)
WHERE 'keyword' IN n.keywords
RETURN n
-- 관계 존재 여부
MATCH (p:Person)
WHERE EXISTS { (p)-[:FOUNDED]->(:Company) }
RETURN p.name1.6 RETURN, ORDER BY, LIMIT
MATCH (p:Person)-[:FOUNDED]->(c:Company)
RETURN p.name AS founder,
c.name AS company,
c.founded AS year
ORDER BY year DESC
LIMIT 101.7 집계 함수
-- 설립한 회사 수 세기
MATCH (p:Person)-[:FOUNDED]->(c:Company)
RETURN p.name, count(c) AS num_companies
ORDER BY num_companies DESC
-- 수집
MATCH (p:Person)-[:FOUNDED]->(c:Company)
RETURN p.name, collect(c.name) AS companies
-- 평균, 최대, 최소
MATCH (c:Company)
RETURN avg(c.employees) AS avg_employees,
max(c.revenue) AS max_revenue1.8 GraphRAG에서 자주 쓰는 패턴
1.8.1 패턴 1: 엔티티 중심 탐색
1.8.2 패턴 2: Multi-hop 경로
1.8.3 패턴 3: 공통 연결 찾기
1.8.4 패턴 4: 유사 노드 그룹핑
1.8.5 패턴 5: 전체 데이터 현황
-- 노드 레이블별 수
MATCH (n)
RETURN labels(n) AS label, count(n) AS count
ORDER BY count DESC
-- 관계 타입별 수
MATCH ()-[r]->()
RETURN type(r) AS type, count(r) AS count
ORDER BY count DESC1.9 CRUD 전체 요약
-- CREATE: 생성
CREATE (n:Label {key: value})
-- READ: 조회
MATCH (n:Label) WHERE n.key = value RETURN n
-- UPDATE: 수정
MATCH (n:Label {key: value})
SET n.new_key = new_value
RETURN n
-- DELETE: 삭제
MATCH (n:Label {key: value})
DETACH DELETE n -- 연결된 관계도 함께 삭제1.10 Python에서 Cypher 실행
from langchain_neo4j import Neo4jGraph
graph = Neo4jGraph(url="bolt://localhost:7687",
username="neo4j", password="password")
# 파라미터로 안전하게 전달 (인젝션 방지)
result = graph.query(
"MATCH (p:Person {name: $name})-[:FOUNDED]->(c:Company) RETURN c.name",
params={"name": "Elon Musk"}
)
print(result)
# [{'c.name': 'Tesla'}, {'c.name': 'SpaceX'}]1.11 정리
생성: CREATE / MERGE
조회: MATCH (n:Label)-[:REL]->(m) WHERE ... RETURN ...
수정: SET n.property = value
삭제: DETACH DELETE n
GraphRAG 핵심 패턴:
단순: MATCH (n)-[:REL]->(m) RETURN m
멀티홉: MATCH (a)-[:REL*1..3]->(b) RETURN b
최단경로: shortestPath((a)-[*]-(b))
다음 파일에서는 LLM으로 텍스트에서 엔티티와 관계를 추출하여 Neo4j에 저장한다.