Neo4j는 Java 기반의 그래프 데이터베이스이며, 실행을 위해서는 JVM 프로세스를 시작해야 하므로 Java SE JDK가 설치되어 있어야 합니다.
Linux 환경 Neo4j 다운로드: https://neo4j.com/download/other-releases/#releases (커뮤니티 에디션은 무료)
압축 해제 후 Neo4j 설정 파일(neo4j.conf)을 수정합니다.
dbms.directories.import:load csv시 파일 경로를 임의의 경로에서 읽을 수 있도록 해당 줄 앞에#을 추가하여 주석 처리합니다 (# dbms.directories.import=import).dbms.memory.heap.initial_size및dbms.memory.heap.max_size: JVM 힙 메모리 초기값과 최대값을 설정합니다. 프로덕션 환경에서는 물리 메모리보다 작은 범위 내에서 최대한 높게 설정하는 것이 좋습니다. (예:dbms.memory.heap.initial_size=5g,dbms.memory.heap.max_size=10g)dbms.memory.pagecache.size: 캐시 크기를 설정합니다. 시스템 사양이 높을수록 크게 설정하는 것이 좋습니다. (예:dbms.memory.pagecache.size=10g)dbms.connectors.default_listen_address: 해당 줄의#을 제거하여 외부 IP로 Neo4j 데이터베이스에 원격 접속할 수 있도록 설정합니다 (dbms.connectors.default_listen_address=0.0.0.0). 기본 포트는 Bolt 7687, HTTP 7474, HTTPS 7473입니다.dbms.connector.bolt.listen_address,dbms.connector.http.listen_address,dbms.connector.https.listen_address: 필요에 따라 Bolt, HTTP, HTTPS 포트를 사용자 정의할 수 있습니다. (예:dbms.connector.http.listen_address=0.0.0.0:7474)dbms.security.allow_csv_import_from_file_urls: 해당 줄의#을 제거하여 원격 URL에서 CSV 파일을 로드할 수 있도록 허용합니다 (dbms.security.allow_csv_import_from_file_urls=true).dbms.shell.enabled: 해당 줄의#을 제거하여 Neo4j 셸을 사용할 수 있도록 활성화합니다 (dbms.shell.enabled=true).dbms.shell.host및dbms.shell.port: Neo4j 셸 접속 호스트 및 포트를 설정합니다. 보안을 위해localhost또는127.0.0.1로 설정하는 것이 권장됩니다. (예:dbms.shell.host=127.0.0.1,dbms.shell.port=1337)dbms.read_only: 해당 줄의#을 제거하여 Neo4j를 읽기/쓰기 모드로 설정합니다 (dbms.read_only=false).
설정 완료 후 다음 명령어를 실행합니다:
./bin/neo4j start
./bin/neo4j stop
./bin/neo4j status
웹 브라우저에서 http://<서버IP>:7474/browser/ 로 접속합니다. 초기 사용자 이름과 비밀번호는 모두 neo4j입니다.
Cypher 쿼리 언어
Cypher는 SQL과 유사한 선언형 그래프 쿼리 언어입니다.
주요 구문:
MATCH: 그래프 패턴을 일치시켜 데이터를 가져옵니다.WHERE:MATCH,OPTIONAL MATCH,WITH절에서 패턴에 대한 제약 조건을 추가하거나 중간 결과를 필터링합니다.CREATE및DELETE: 노드와 관계를 생성하거나 삭제합니다.SET및REMOVE:SET은 속성 값을 설정하거나 노드에 레이블을 추가하고,REMOVE는 속성이나 레이블을 제거합니다.MERGE: 기존 패턴과 일치하거나 새 패턴을 생성합니다. 고유성 제약 조건이 있는 경우 유용합니다.RETURN: 쿼리 결과를 정의합니다.
Cypher의 세 가지 요소:
- 노드 구문: 원형 괄호
()로 표현됩니다.
n: 노드의 변수명.:Label: 노드의 레이블(타입). 여러 개 지정 가능.{key: value}: 노드의 속성 (Python 딕셔너리와 유사).- 예:
(node:Person {name: 'Alice'})
- 관계 구문: 대시
-와 화살표->,< -를 사용하여 표현하며, 대괄호[]안에 상세 정보를 추가합니다.
r: 관계의 변수명.:RelationshipType: 관계의 타입.{key: value}: 관계의 속성.- 예:
(person)-[:KNOWS]->(friend)또는(parent)-[rel:DIRECTED {since: 2020}]->(child)
- 패턴 구문:
노드 - 관계 - 노드형식으로 표현됩니다.
- 예:
(a)-[r:RELATIONSHIP]->(b)
노드 조작
- 노드 생성:
CREATE (:Test {id: '123456', name: 'Alice', address: 'Seoul'})
CREATE (:TestParent {id: '789012', name: 'Bob', address: 'Busan'})
- 관계 생성:
- 속성 없는 관계:
MATCH (t:Test {id: '123456'}), (p:TestParent {id: '789012'})
CREATE (p)-[r:DIRECTED]->(t)
- 속성 있는 관계:
MATCH (t:Test {id: '123456'}), (p:TestParent {id: '789012'})
CREATE (p)-[r:ACTED_IN {role: 'parent'}]->(t)
- 지정된 관계 삭제:
MATCH (t:Test)-[r:DIRECTED]-(p:TestParent)
DELETE r
- 연결되지 않은 모든 노드 삭제:
MATCH (n) WHERE NOT (n)--()
DELETE n
노드 및 관계 조회
MATCH 절로 패턴을 지정하고, WHERE 절로 조건을 추가하며, RETURN 절로 결과를 반환합니다.
- 전체 그래프 조회:
MATCH (n)
RETURN n
- 이름이 'Alice'인 노드 조회:
MATCH (n) WHERE n.name = 'Alice'
RETURN n
- 특정 노드와 관계가 있는 노드 조회:
MATCH (n)--(test:TestParent)
RETURN n
- 기본 조회:
MATCH (s:School)
RETURN s
LIMIT 25
- 관계가 있는 조회:
MATCH (a:Academy)-[:Belong_to]->(s:School)
RETURN a, s
LIMIT 15
- 조건부 관계 조회:
MATCH (d:Discipline)-[:Belong_to]->(a:Academy)
WHERE a.academy_id = "19"
RETURN d, a
LIMIT 30
- 다차원 연관 조회:
MATCH (p:Project)-[:Be_from]->(d:Discipline)-[:Belong_to]->(a:Academy)
WHERE a.academy_name = "기계공학부"
RETURN p, d, a
LIMIT 10
- 제한 없는 관계 조회:
MATCH n = ()-[:Belong_to]-()
RETURN n
LIMIT 50
- 정규 표현식/퍼지 매칭 조회:
MATCH (s:School)
WHERE s.school_name =~ "서울.*"
RETURN s
LIMIT 10
- 포함 조회:
MATCH (p:Project)
WHERE p.project_name CONTAINS "네트워크"
RETURN p
LIMIT 10
- 엔티티 간 관계 경로 조회:
- 모든 관계 경로 조회:
MATCH r = (a:Star {name: 'Tom Hanks'})-[*..5]->(b:Star {name: 'Meg Ryan'})
RETURN r
- 최단 경로 조회:
MATCH r = shortestPath((a:Star {name: 'Tom Hanks'})-[*..5]->(b:Star {name: 'Meg Ryan'}))
RETURN r
그래프 조작 업데이트
SET 절은 노드의 레이블 및 속성을 업데이트하고, REMOVE 절은 속성 및 노드 레이블을 제거합니다.
- 노드에 속성 추가: 노드 ID를 사용하여 노드를 찾습니다.
id()함수를 활용하는 것이 권장됩니다.
MATCH (n) WHERE id(n) = 40
SET n.newProperty = 'newValue'
RETURN n
- 노드에 레이블 추가:
MATCH (n) WHERE id(n) = 40
SET n:Company
RETURN n
- 관계에 속성 추가:
MATCH (m)-[r]->(n)
WHERE id(n) = 7 AND id(m) = 8
SET r.team = 'Neo4j'
RETURN n
패턴
패턴은 데이터를 검색하는 방법을 설명합니다. ()는 노드를, []는 관계를 나타냅니다.
- 노드 패턴:
(n): 노드 변수n. 익명 노드는().(n:Label): 특정 레이블Label을 가진 노드. 여러 레이블 지정 가능.(n {name: "Vic"}):name속성값이 "Vic"인 노드. 여러 속성 지정 가능.(n:Label {name: "Vic"}): 특정 레이블과 속성을 가진 노드.
- 관계 패턴:
[r]: 관계 변수r. 익명 관계는[].[r:Type]: 관계 타입이Type인 관계. 관계는 반드시 하나의 타입을 가져야 함.[r:Type {name: "Friend"}]: 타입이Type이고name속성값이 "Friend"인 관계.
- 연결 노드 패턴:
(a)-[r]->(b): 노드a와b사이에 방향이 있는 관계r.(a)-->(b):a에서b로 향하는 관계 (관계 타입 및 변수 생략).(a)-(b):a와b사이에 연결된 관계 (방향 무시).
- 가변 길이 경로 패턴:
[*N..M]: 경로 길이의 최소값N, 최대값M.[*2]: 길이가 2인 경로.[*3..5]: 길이가 3에서 5 사이인 경로.[*..5]: 최대 길이가 5인 경로.[*3..]: 최소 길이가 3인 경로.[*]: 경로 길이 제한 없음.- 예:
MATCH (a)-[*..2]-(b) WHERE a.name = 'Filipa' RETURN b.name
- 경로 변수: 경로를 변수에 할당하여 참조할 수 있습니다.
p = (a)-[*3..5]->(b)
Spring Boot와 Neo4j 통합
Spring Boot 2.x 버전은 Neo4j와의 통합 방식이 변경되었습니다. 다음은 Spring Boot 2.x 기반의 통합 예시입니다.
- 의존성 추가 (pom.xml):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
application.properties설정:
spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.username=neo4j
spring.neo4j.password=your_password
- Neo4j 설정 클래스:
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
@Configuration
@EnableNeo4jRepositories(basePackages = "com.example.repository") // Repository 패키지 지정
public class Neo4jConfig {
// 필요한 경우 추가 설정
}
@EnableNeo4jRepositories: Spring Data Neo4j가 Repository를 스캔할 패키지를 지정합니다.
- 엔티티 클래스 생성:
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
@Node
public class Person {
@Id
@GeneratedValue
private Long id; // Neo4j 내부 ID, @Id로 지정
@Property("name") // DB 속성 이름
private String name;
@Property("age")
private int age;
// getters and setters
}
@Node: Neo4j 노드를 나타내는 클래스임을 명시합니다.@Id: 노드의 고유 식별자. Neo4j는 내부적으로 ID를 관리합니다.@GeneratedValue: ID 값을 자동으로 생성합니다.@Property: Neo4j 속성과의 매핑을 정의합니다.
- Repository 인터페이스 생성:
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface PersonRepository extends Neo4jRepository<Person, Long> {
@Query("MATCH (p:Person) WHERE p.name = $name RETURN p")
List<Person> findByNameCustom(String name);
List<Person> findByAgeGreaterThan(int age);
}
Neo4jRepository<Entity, ID>: 기본적인 CRUD 작업을 제공합니다.@Query: 네이티브 Cypher 쿼리를 실행할 때 사용합니다. 파라미터는$parameterName형식으로 전달합니다.
- Service 및 Controller 테스트:
// Service 클래스 예시
@Service
public class PersonService {
@Autowired
private PersonRepository personRepository;
public List<Person> findPersonsByName(String name) {
return personRepository.findByNameCustom(name);
}
public List<Person> findPersonsOlderThan(int age) {
return personRepository.findByAgeGreaterThan(age);
}
public Person createPerson(Person person) {
return personRepository.save(person);
}
}
// Controller 클래스 예시
@RestController
@RequestMapping("/api/persons")
public class PersonController {
@Autowired
private PersonService personService;
@GetMapping("/name/{name}")
public List<Person> getPersonsByName(@PathVariable String name) {
return personService.findPersonsByName(name);
}
@PostMapping
public Person createPerson(@RequestBody Person person) {
return personService.createPerson(person);
}
}
이제 /api/persons/name/Alice 와 같은 요청으로 데이터를 조회할 수 있습니다.