docs: GraphRAG 및 그래프 DB 전환 기획 문서 추가
약국 POS 시스템의 GraphRAG 기반 추천 시스템 구축 관련 문서:
## 핵심 설계 문서
1. 질병코드기반 제품추천.md
- ICD-10 질병 코드 활용 추천 시스템 설계
- 계층 구조 (질병 → 질병군 → 제품군 → 개별 제품)
- 처방전 기반 추천 알고리즘
2. complex-product-graph-modeling.md
- 복합제(비맥스제트 등) 그래프 모델링
- 성분 간 시너지 효과 표현
- 복합 증상 매칭 쿼리 예시
3. pubmed-graphrag-workflow.md
- PubMed → GraphRAG 전체 워크플로우 (5단계)
- 논문 검색, 근거 추출, 지식 그래프 구축
- MCP Server 개발 가이드
## 그래프 DB 비교 및 평가
4. sqlite-graph-evaluation.md
- SQLite vs SQLite-Graph vs Neo4j 비교
- 현 시점(2026-01) 평가: 기존 SQL 유지 권장
- 6개월 후 재평가 계획
5. opensource-graph-db-comparison.md
- 오픈소스 그래프 DB 비교 (Neo4j, ArangoDB 등)
6. 온톨로지로전환.md
- 관계형 DB → 온톨로지 구조 전환 가이드
- PubMed RAG 활용 방안
- 추론 규칙 설계
## PubMed GraphRAG 활용
7. pycnogenol-multi-indication-graphrag.md
- 피크노제놀 다중 적응증 GraphRAG 구축 사례
- 7가지 적응증별 근거 수준
8. grpahrag_아쉬아간다.md
- Ashwagandha GraphRAG 구축 사례
9. pubdmed이용ai.md
- PubMed + AI 통합 활용 가이드
## 추가 워크플로우
10. pubmed-graphrag-workflow_next.md
- 다음 단계 워크플로우
11. PostgresGRAPH전환.md
- PostgreSQL + Apache AGE 전환 가이드
모든 문서는 한국어로 작성되었으며, 코드 예시는 영어로 포함.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
657
docs/opensource-graph-db-comparison.md
Normal file
657
docs/opensource-graph-db-comparison.md
Normal file
@@ -0,0 +1,657 @@
|
||||
# 오픈소스 그래프 DB 비교 및 추천
|
||||
|
||||
> Neo4j 대신 사용할 수 있는 오픈소스 그래프 데이터베이스 옵션
|
||||
|
||||
**작성일**: 2026-01-24
|
||||
**대상 프로젝트**: 약국 POS QR 시스템 (PubMed GraphRAG)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 평가 기준
|
||||
|
||||
우리 프로젝트에 필요한 조건:
|
||||
```
|
||||
✅ 완전한 오픈소스 (상업적 제약 없음)
|
||||
✅ Cypher 또는 유사 쿼리 언어 지원
|
||||
✅ Python 통합 용이
|
||||
✅ 배포 간편 (별도 서버 최소화)
|
||||
✅ SQLite/PostgreSQL 같은 익숙한 DB와 통합
|
||||
✅ 중소 규모 그래프 최적화 (1,000~10,000 노드)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 오픈소스 그래프 DB 비교
|
||||
|
||||
### 1. **Apache AGE** ⭐⭐⭐⭐⭐ 최고 추천!
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ PostgreSQL + 그래프 = Apache AGE │
|
||||
│ "기존 PostgreSQL에 그래프 기능 추가" │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 🌟 핵심 특징
|
||||
- **PostgreSQL 확장** (익숙한 DB + 그래프 기능)
|
||||
- **Cypher 쿼리 완벽 지원** (Neo4j와 동일)
|
||||
- **SQL + Cypher 혼합 사용 가능**
|
||||
- **Apache 2.0 라이선스** (완전 오픈소스)
|
||||
- **기존 PostgreSQL 데이터와 그래프 결합 가능**
|
||||
|
||||
#### ✅ 장점
|
||||
```python
|
||||
# SQL과 Cypher를 함께 사용!
|
||||
# 기존 테이블 (users, products)
|
||||
SELECT * FROM users WHERE age > 30;
|
||||
|
||||
# 그래프 쿼리 (관계 탐색)
|
||||
SELECT * FROM cypher('graph_name', $$
|
||||
MATCH (u:User)-[:PURCHASED]->(p:Product)
|
||||
WHERE u.age > 30
|
||||
RETURN u.name, p.name
|
||||
$$) AS (user_name text, product_name text);
|
||||
```
|
||||
|
||||
#### ⚠️ 단점
|
||||
- PostgreSQL 필요 (SQLite보다 무거움)
|
||||
- 비교적 신생 프로젝트 (2020년 시작)
|
||||
|
||||
#### 📦 설치 (Ubuntu/Debian 예시)
|
||||
```bash
|
||||
# PostgreSQL 설치
|
||||
sudo apt-get install postgresql-14
|
||||
|
||||
# Apache AGE 설치
|
||||
sudo apt-get install postgresql-14-age
|
||||
|
||||
# 확장 활성화
|
||||
CREATE EXTENSION age;
|
||||
```
|
||||
|
||||
#### 🐍 Python 사용
|
||||
```python
|
||||
import psycopg2
|
||||
from age import Age
|
||||
|
||||
conn = psycopg2.connect(
|
||||
host="localhost",
|
||||
database="pharmacy_db",
|
||||
user="postgres"
|
||||
)
|
||||
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 그래프 생성
|
||||
cursor.execute("""
|
||||
SELECT create_graph('pharmacy_graph');
|
||||
""")
|
||||
|
||||
# Cypher 쿼리
|
||||
cursor.execute("""
|
||||
SELECT * FROM cypher('pharmacy_graph', $$
|
||||
CREATE (n:Drug {name: 'Naproxen', type: 'NSAID'})
|
||||
RETURN n
|
||||
$$) AS (drug agtype);
|
||||
""")
|
||||
|
||||
# 경로 탐색
|
||||
cursor.execute("""
|
||||
SELECT * FROM cypher('pharmacy_graph', $$
|
||||
MATCH path = (d:Drug {name: 'Statin'})-[*1..3]->(s:Symptom)
|
||||
RETURN path
|
||||
$$) AS (path agtype);
|
||||
""")
|
||||
```
|
||||
|
||||
#### 🎯 우리 프로젝트 적용
|
||||
```
|
||||
현재: SQLite (mileage.db)
|
||||
↓
|
||||
마이그레이션: PostgreSQL + Apache AGE
|
||||
↓
|
||||
장점:
|
||||
- 기존 users, transactions 테이블 유지 (SQL)
|
||||
- 약물-증상 관계는 그래프 (Cypher)
|
||||
- 한 DB에서 모두 처리 ✨
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2. **Memgraph** ⭐⭐⭐⭐
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 빠른 인메모리 그래프 DB │
|
||||
│ "Neo4j와 호환되는 Cypher 지원" │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 🌟 핵심 특징
|
||||
- **완전한 Cypher 지원** (Neo4j 호환)
|
||||
- **인메모리 처리** (매우 빠름)
|
||||
- **스트림 처리 지원** (Kafka 통합)
|
||||
- **BSL 라이선스** (Community Edition 무료)
|
||||
|
||||
#### ✅ 장점
|
||||
- Neo4j보다 빠름 (인메모리)
|
||||
- 완전한 Cypher 지원 (학습 곡선 낮음)
|
||||
- Python 라이브러리 우수
|
||||
|
||||
#### ⚠️ 단점
|
||||
- 별도 서버 필요
|
||||
- 인메모리 → 메모리 많이 필요
|
||||
- 데이터 영속성 설정 필요
|
||||
|
||||
#### 🐍 Python 사용
|
||||
```python
|
||||
from gqlalchemy import Memgraph
|
||||
|
||||
memgraph = Memgraph(host='127.0.0.1', port=7687)
|
||||
|
||||
# Cypher 쿼리 (Neo4j와 동일)
|
||||
results = memgraph.execute_and_fetch("""
|
||||
MATCH (d:Drug {name: 'Naproxen'})-[:SAFER_THAN]->(other:Drug)
|
||||
RETURN d.name, other.name
|
||||
""")
|
||||
|
||||
for result in results:
|
||||
print(result['d.name'], result['other.name'])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3. **ArangoDB** ⭐⭐⭐⭐
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 멀티모델 DB (문서 + 그래프 + 키-밸류) │
|
||||
│ "하나의 DB로 모든 데이터 모델 지원" │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 🌟 핵심 특징
|
||||
- **멀티모델**: 문서(JSON) + 그래프 + 키-밸류
|
||||
- **AQL 쿼리 언어** (Cypher와 유사, 더 강력)
|
||||
- **완전 오픈소스** (Apache 2.0)
|
||||
- **Python, JavaScript 등 다양한 드라이버**
|
||||
|
||||
#### ✅ 장점
|
||||
- 유연함 (그래프 + JSON 문서 모두 저장)
|
||||
- 성능 우수
|
||||
- 웹 UI 기본 제공
|
||||
|
||||
#### ⚠️ 단점
|
||||
- Cypher 아님 (AQL 학습 필요)
|
||||
- 별도 서버 필요
|
||||
- 설정 복잡할 수 있음
|
||||
|
||||
#### 🐍 Python 사용
|
||||
```python
|
||||
from arango import ArangoClient
|
||||
|
||||
client = ArangoClient(hosts='http://localhost:8529')
|
||||
db = client.db('pharmacy_db', username='root', password='password')
|
||||
|
||||
# 그래프 생성
|
||||
graph = db.create_graph('pharmacy_graph')
|
||||
|
||||
# 문서 + 그래프 혼합 (강력!)
|
||||
result = db.aql.execute("""
|
||||
FOR drug IN drugs
|
||||
FILTER drug.type == 'NSAID'
|
||||
FOR vertex, edge, path IN 1..3 OUTBOUND drug GRAPH 'pharmacy_graph'
|
||||
FILTER vertex._id == 'symptoms/pain'
|
||||
RETURN path
|
||||
""")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dgraph** ⭐⭐⭐
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ GraphQL 네이티브 그래프 DB │
|
||||
│ "GraphQL로 그래프 쿼리" │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 🌟 핵심 특징
|
||||
- **GraphQL 쿼리 언어** (Cypher 대신)
|
||||
- **Go로 작성** (빠르고 가벼움)
|
||||
- **분산 처리 지원**
|
||||
- **Apache 2.0 라이선스**
|
||||
|
||||
#### ✅ 장점
|
||||
- GraphQL 사용 시 최적
|
||||
- 성능 우수
|
||||
- 분산 확장 용이
|
||||
|
||||
#### ⚠️ 단점
|
||||
- Cypher 미지원 (GraphQL 학습 필요)
|
||||
- 별도 서버 필요
|
||||
- 커뮤니티 Neo4j보다 작음
|
||||
|
||||
---
|
||||
|
||||
### 5. **JanusGraph** ⭐⭐⭐
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Apache 재단 대규모 그래프 DB │
|
||||
│ "수억 개 노드 지원" │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 🌟 핵심 특징
|
||||
- **Apache 재단 공식 프로젝트**
|
||||
- **대규모 그래프 최적화** (수십억 엣지)
|
||||
- **Gremlin 쿼리 언어** (Cypher 아님)
|
||||
- **다양한 백엔드 지원** (Cassandra, HBase 등)
|
||||
|
||||
#### ✅ 장점
|
||||
- 대규모 그래프에 최적
|
||||
- Apache 재단 신뢰성
|
||||
- 엔터프라이즈급 기능
|
||||
|
||||
#### ⚠️ 단점
|
||||
- **우리 프로젝트에 과함** (중소 규모용 아님)
|
||||
- 설정 매우 복잡
|
||||
- Gremlin 학습 곡선 높음
|
||||
|
||||
---
|
||||
|
||||
### 6. **Nebula Graph** ⭐⭐⭐
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ 분산 그래프 DB │
|
||||
│ "중국발 오픈소스, 빠른 성능" │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### 🌟 핵심 특징
|
||||
- **nGQL** (Cypher와 유사)
|
||||
- **분산 아키텍처**
|
||||
- **Apache 2.0 라이선스**
|
||||
|
||||
#### ⚠️ 단점
|
||||
- 별도 서버 (Meta, Graph, Storage)
|
||||
- 설정 복잡
|
||||
- 커뮤니티 주로 중국어
|
||||
|
||||
---
|
||||
|
||||
## 🏆 종합 비교표
|
||||
|
||||
```
|
||||
┌─────────────┬──────────┬──────────┬──────────┬──────────┬──────────┐
|
||||
│ 항목 │ AGE │ Memgraph │ ArangoDB │ Dgraph │ JanusGrph│
|
||||
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ 쿼리 언어 │ Cypher │ Cypher │ AQL │ GraphQL │ Gremlin │
|
||||
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ 배포 난이도 │ ⭐⭐ │ ⭐⭐⭐ │ ⭐⭐⭐ │ ⭐⭐⭐ │ ⭐⭐⭐⭐⭐│
|
||||
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ 학습 곡선 │ ⭐ │ ⭐ │ ⭐⭐ │ ⭐⭐ │ ⭐⭐⭐⭐ │
|
||||
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ 성능 │ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐⭐│ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐ │ ⭐⭐⭐⭐⭐│
|
||||
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ SQL 통합 │ ✅ │ ❌ │ ❌ │ ❌ │ ❌ │
|
||||
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ 중소규모 적합│ ✅ │ ✅ │ ✅ │ ⭐⭐ │ ❌ │
|
||||
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ 라이선스 │ Apache │ BSL │ Apache │ Apache │ Apache │
|
||||
├─────────────┼──────────┼──────────┼──────────┼──────────┼──────────┤
|
||||
│ 우리적합도 │⭐⭐⭐⭐⭐│ ⭐⭐⭐⭐ │ ⭐⭐⭐ │ ⭐⭐ │ ⭐ │
|
||||
└─────────────┴──────────┴──────────┴──────────┴──────────┴──────────┘
|
||||
|
||||
⭐ 적음/쉬움/낮음 = 좋음
|
||||
⭐⭐⭐⭐⭐ 많음/어려움/높음 = 나쁨 (배포, 학습 곡선)
|
||||
⭐⭐⭐⭐⭐ 많음 = 좋음 (성능, 적합도)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 우리 프로젝트 최적 선택
|
||||
|
||||
### 🥇 1순위: **Apache AGE**
|
||||
|
||||
#### 선택 이유
|
||||
```
|
||||
✅ PostgreSQL 확장 (익숙한 환경)
|
||||
✅ SQL + Cypher 혼합 사용 (마이그레이션 쉬움)
|
||||
✅ 기존 데이터 + 그래프 한 DB에서 관리
|
||||
✅ 완전 오픈소스 (Apache 2.0)
|
||||
✅ 배포 간단 (PostgreSQL만 있으면 됨)
|
||||
```
|
||||
|
||||
#### 마이그레이션 경로
|
||||
```
|
||||
현재: SQLite
|
||||
↓
|
||||
1단계: PostgreSQL + 기본 테이블 마이그레이션
|
||||
↓
|
||||
2단계: Apache AGE 확장 설치
|
||||
↓
|
||||
3단계: 그래프 노드/엣지 생성
|
||||
↓
|
||||
결과: SQL (users, transactions) + Cypher (약물 관계)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🥈 2순위: **Memgraph**
|
||||
|
||||
#### 선택 이유
|
||||
```
|
||||
✅ 완전한 Cypher 지원 (Neo4j 호환)
|
||||
✅ 매우 빠름 (인메모리)
|
||||
✅ Python 라이브러리 우수
|
||||
```
|
||||
|
||||
#### 적합한 경우
|
||||
```
|
||||
- 실시간 추천이 매우 중요
|
||||
- 메모리 충분히 있음
|
||||
- 별도 서버 운영 가능
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🥉 3순위: **ArangoDB**
|
||||
|
||||
#### 선택 이유
|
||||
```
|
||||
✅ 멀티모델 (유연함)
|
||||
✅ 성능 우수
|
||||
✅ 웹 UI 좋음
|
||||
```
|
||||
|
||||
#### 적합한 경우
|
||||
```
|
||||
- JSON 문서 + 그래프 모두 필요
|
||||
- AQL 학습 가능
|
||||
- 다양한 데이터 모델 실험
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Apache AGE 실전 적용 가이드
|
||||
|
||||
### 1. 설치 (Docker 사용)
|
||||
|
||||
```bash
|
||||
# Docker Compose 설정
|
||||
# docker-compose.yml
|
||||
version: '3.8'
|
||||
services:
|
||||
postgres-age:
|
||||
image: apache/age:latest
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: password
|
||||
POSTGRES_DB: pharmacy_db
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
```
|
||||
|
||||
```bash
|
||||
# 실행
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 2. Python 통합
|
||||
|
||||
```python
|
||||
"""
|
||||
Apache AGE + Python 예시
|
||||
"""
|
||||
import psycopg2
|
||||
from age import Age
|
||||
|
||||
# 연결
|
||||
conn = psycopg2.connect(
|
||||
host="localhost",
|
||||
database="pharmacy_db",
|
||||
user="postgres",
|
||||
password="password"
|
||||
)
|
||||
|
||||
age = Age(conn)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# 1. 그래프 생성
|
||||
age.setGraph('pharmacy_graph')
|
||||
cursor.execute("SELECT create_graph('pharmacy_graph');")
|
||||
|
||||
# 2. 노드 생성 (Cypher)
|
||||
cursor.execute("""
|
||||
SELECT * FROM cypher('pharmacy_graph', $$
|
||||
CREATE (statin:Drug {name: 'Statin', type: 'HMG-CoA inhibitor'}),
|
||||
(coq10:Drug {name: 'CoQ10', type: 'Supplement'}),
|
||||
(myopathy:Condition {name: 'Myopathy'}),
|
||||
(evidence:Evidence {pmid: '30371340', reliability: 0.95})
|
||||
RETURN statin, coq10, myopathy, evidence
|
||||
$$) AS (statin agtype, coq10 agtype, myopathy agtype, evidence agtype);
|
||||
""")
|
||||
|
||||
# 3. 관계 생성
|
||||
cursor.execute("""
|
||||
SELECT * FROM cypher('pharmacy_graph', $$
|
||||
MATCH (statin:Drug {name: 'Statin'}),
|
||||
(coq10:Drug {name: 'CoQ10'}),
|
||||
(myopathy:Condition {name: 'Myopathy'}),
|
||||
(evidence:Evidence {pmid: '30371340'})
|
||||
CREATE (statin)-[:INHIBITS {mechanism: 'HMG-CoA pathway'}]->(coq10),
|
||||
(coq10)-[:REDUCES {effect_size: -1.60, p_value: 0.001}]->(myopathy),
|
||||
(evidence)-[:SUPPORTS]->(coq10)-[:REDUCES]->(myopathy)
|
||||
RETURN statin, coq10, myopathy
|
||||
$$) AS (statin agtype, coq10 agtype, myopathy agtype);
|
||||
""")
|
||||
|
||||
# 4. 경로 탐색 (GraphRAG!)
|
||||
cursor.execute("""
|
||||
SELECT * FROM cypher('pharmacy_graph', $$
|
||||
MATCH path = (statin:Drug {name: 'Statin'})-[*1..3]->(myopathy:Condition {name: 'Myopathy'})
|
||||
RETURN path
|
||||
$$) AS (path agtype);
|
||||
""")
|
||||
|
||||
results = cursor.fetchall()
|
||||
for row in results:
|
||||
print(row[0])
|
||||
|
||||
# 5. SQL + Cypher 혼합!
|
||||
cursor.execute("""
|
||||
-- SQL: 사용자 조회
|
||||
WITH high_risk_users AS (
|
||||
SELECT id, name, age
|
||||
FROM users
|
||||
WHERE age > 60 AND has_hypertension = true
|
||||
)
|
||||
-- Cypher: 안전한 약물 추천
|
||||
SELECT u.name, drug_name
|
||||
FROM high_risk_users u,
|
||||
LATERAL (
|
||||
SELECT * FROM cypher('pharmacy_graph', $$
|
||||
MATCH (drug:Drug)-[:SAFE_FOR]->(profile:PatientProfile {name: 'Elderly_HTN'})
|
||||
RETURN drug.name
|
||||
$$) AS (drug_name agtype)
|
||||
);
|
||||
""")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
```
|
||||
|
||||
### 3. 실제 추천 시스템 예시
|
||||
|
||||
```python
|
||||
"""
|
||||
Apache AGE 기반 약물 추천 시스템
|
||||
"""
|
||||
|
||||
class DrugRecommender:
|
||||
def __init__(self, conn):
|
||||
self.conn = conn
|
||||
self.cursor = conn.cursor()
|
||||
|
||||
def recommend(self, patient_id, symptom):
|
||||
"""
|
||||
환자 프로필 + 증상 → 약물 추천 (근거 포함)
|
||||
"""
|
||||
# 1. SQL: 환자 정보 조회
|
||||
self.cursor.execute("""
|
||||
SELECT age, hypertension, diabetes
|
||||
FROM users
|
||||
WHERE id = %s
|
||||
""", (patient_id,))
|
||||
|
||||
patient = self.cursor.fetchone()
|
||||
age, has_htn, has_dm = patient
|
||||
|
||||
# 2. 환자 프로필 결정
|
||||
if has_htn and has_dm:
|
||||
profile = 'Patient_HTN_DM'
|
||||
elif has_htn:
|
||||
profile = 'Patient_HTN'
|
||||
elif age > 65:
|
||||
profile = 'Elderly'
|
||||
else:
|
||||
profile = 'General'
|
||||
|
||||
# 3. Cypher: 그래프 기반 추천
|
||||
self.cursor.execute(f"""
|
||||
SELECT * FROM cypher('pharmacy_graph', $$
|
||||
MATCH (drug:Drug)-[treats:TREATS]->(condition:Condition {{name: '{symptom}'}})
|
||||
WHERE NOT (drug)-[:CONTRAINDICATED_IN]->(:PatientProfile {{name: '{profile}'}})
|
||||
MATCH (evidence:Evidence)-[:SUPPORTS]->(treats)
|
||||
RETURN
|
||||
drug.name AS drug,
|
||||
treats.effect_size AS effect,
|
||||
evidence.pmid AS pmid,
|
||||
evidence.reliability AS reliability
|
||||
ORDER BY evidence.reliability DESC, treats.effect_size DESC
|
||||
LIMIT 1
|
||||
$$) AS (drug agtype, effect agtype, pmid agtype, reliability agtype);
|
||||
""")
|
||||
|
||||
result = self.cursor.fetchone()
|
||||
|
||||
if result:
|
||||
return {
|
||||
'drug': result[0],
|
||||
'effect_size': result[1],
|
||||
'evidence_pmid': result[2],
|
||||
'reliability': result[3],
|
||||
'patient_profile': profile
|
||||
}
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
# 사용 예시
|
||||
recommender = DrugRecommender(conn)
|
||||
|
||||
# 환자 ID 123, 증상 "Pain"
|
||||
recommendation = recommender.recommend(patient_id=123, symptom='Pain')
|
||||
|
||||
print(recommendation)
|
||||
# {
|
||||
# 'drug': 'Naproxen',
|
||||
# 'effect_size': -1.8,
|
||||
# 'evidence_pmid': '27959716',
|
||||
# 'reliability': 0.99,
|
||||
# 'patient_profile': 'Patient_HTN_DM'
|
||||
# }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 마이그레이션 로드맵
|
||||
|
||||
### Phase 1: SQLite → PostgreSQL (1주)
|
||||
```sql
|
||||
-- 기존 SQLite 테이블 PostgreSQL로 이동
|
||||
-- users, transactions, mileage_ledger 등
|
||||
```
|
||||
|
||||
### Phase 2: Apache AGE 설치 (1일)
|
||||
```bash
|
||||
CREATE EXTENSION age;
|
||||
SELECT create_graph('pharmacy_graph');
|
||||
```
|
||||
|
||||
### Phase 3: 그래프 데이터 생성 (1주)
|
||||
```python
|
||||
# PubMed 논문 → 그래프 트리플
|
||||
# Cypher CREATE 문으로 노드/엣지 생성
|
||||
```
|
||||
|
||||
### Phase 4: 추천 시스템 업그레이드 (1주)
|
||||
```python
|
||||
# SQL + Cypher 혼합 쿼리
|
||||
# GraphRAG 추론 경로 자동 생성
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 최종 권장사항
|
||||
|
||||
### ✅ **즉시 도입 가능: Apache AGE**
|
||||
|
||||
**선택 이유**:
|
||||
1. PostgreSQL 확장 (익숙함)
|
||||
2. SQL + Cypher 모두 사용 가능
|
||||
3. 기존 데이터 + 그래프 한 DB
|
||||
4. 완전 오픈소스
|
||||
5. 마이그레이션 쉬움
|
||||
|
||||
**시작 단계**:
|
||||
```bash
|
||||
# 1. Docker로 테스트
|
||||
docker run -p 5432:5432 apache/age
|
||||
|
||||
# 2. Python 라이브러리 설치
|
||||
pip install psycopg2-binary age
|
||||
|
||||
# 3. 간단한 그래프 생성 테스트
|
||||
python test_age.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 🔮 **대안: Memgraph** (성능 최우선 시)
|
||||
|
||||
**조건**:
|
||||
- 별도 서버 운영 가능
|
||||
- 메모리 충분 (8GB+)
|
||||
- 실시간 추천 필수
|
||||
|
||||
---
|
||||
|
||||
## 📚 참고 링크
|
||||
|
||||
- **Apache AGE**: https://age.apache.org/
|
||||
- GitHub: https://github.com/apache/age
|
||||
- 문서: https://age.apache.org/age-manual/master/index.html
|
||||
|
||||
- **Memgraph**: https://memgraph.com/
|
||||
- 문서: https://memgraph.com/docs
|
||||
|
||||
- **ArangoDB**: https://www.arangodb.com/
|
||||
- 문서: https://www.arangodb.com/docs/
|
||||
|
||||
- **Dgraph**: https://dgraph.io/
|
||||
- GitHub: https://github.com/dgraph-io/dgraph
|
||||
|
||||
---
|
||||
|
||||
**작성**: 2026-01-24
|
||||
**추천**: Apache AGE ⭐⭐⭐⭐⭐
|
||||
Reference in New Issue
Block a user