Neo4j 그래프 데이터베이스 및 Cypher 쿼리 언어 학습 및 활용

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_sizedbms.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.hostdbms.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 절에서 패턴에 대한 제약 조건을 추가하거나 중간 결과를 필터링합니다.
  • CREATEDELETE: 노드와 관계를 생성하거나 삭제합니다.
  • SETREMOVE: SET은 속성 값을 설정하거나 노드에 레이블을 추가하고, REMOVE는 속성이나 레이블을 제거합니다.
  • MERGE: 기존 패턴과 일치하거나 새 패턴을 생성합니다. 고유성 제약 조건이 있는 경우 유용합니다.
  • RETURN: 쿼리 결과를 정의합니다.

Cypher의 세 가지 요소:

  1. 노드 구문: 원형 괄호 ()로 표현됩니다.
  • n: 노드의 변수명.
  • :Label: 노드의 레이블(타입). 여러 개 지정 가능.
  • {key: value}: 노드의 속성 (Python 딕셔너리와 유사).
  • 예: (node:Person {name: 'Alice'})
  1. 관계 구문: 대시 - 와 화살표 ->, < - 를 사용하여 표현하며, 대괄호 [] 안에 상세 정보를 추가합니다.
  • r: 관계의 변수명.
  • :RelationshipType: 관계의 타입.
  • {key: value}: 관계의 속성.
  • 예: (person)-[:KNOWS]->(friend) 또는 (parent)-[rel:DIRECTED {since: 2020}]->(child)
  1. 패턴 구문: 노드 - 관계 - 노드 형식으로 표현됩니다.
  • 예: (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

패턴

패턴은 데이터를 검색하는 방법을 설명합니다. ()는 노드를, []는 관계를 나타냅니다.

  1. 노드 패턴:
  • (n): 노드 변수 n. 익명 노드는 ().
  • (n:Label): 특정 레이블 Label을 가진 노드. 여러 레이블 지정 가능.
  • (n {name: "Vic"}): name 속성값이 "Vic"인 노드. 여러 속성 지정 가능.
  • (n:Label {name: "Vic"}): 특정 레이블과 속성을 가진 노드.
  1. 관계 패턴:
  • [r]: 관계 변수 r. 익명 관계는 [].
  • [r:Type]: 관계 타입이 Type인 관계. 관계는 반드시 하나의 타입을 가져야 함.
  • [r:Type {name: "Friend"}]: 타입이 Type이고 name 속성값이 "Friend"인 관계.
  1. 연결 노드 패턴:
  • (a)-[r]->(b): 노드 ab 사이에 방향이 있는 관계 r.
  • (a)-->(b): a에서 b로 향하는 관계 (관계 타입 및 변수 생략).
  • (a)-(b): ab 사이에 연결된 관계 (방향 무시).
  1. 가변 길이 경로 패턴:
  • [*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
  1. 경로 변수: 경로를 변수에 할당하여 참조할 수 있습니다.
p = (a)-[*3..5]->(b)

Spring Boot와 Neo4j 통합

Spring Boot 2.x 버전은 Neo4j와의 통합 방식이 변경되었습니다. 다음은 Spring Boot 2.x 기반의 통합 예시입니다.

  1. 의존성 추가 (pom.xml):
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
  1. application.properties 설정:
spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.username=neo4j
spring.neo4j.password=your_password
  1. 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를 스캔할 패키지를 지정합니다.
  1. 엔티티 클래스 생성:
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 속성과의 매핑을 정의합니다.
  1. 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 형식으로 전달합니다.
  1. 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 와 같은 요청으로 데이터를 조회할 수 있습니다.

태그: Neo4j Graph Database Cypher Spring Boot java

8월 1일 06:07에 게시됨