728x90
반응형

계속 적을 글

  • 본 글은 계속해서 적어갈 예정

Create

  • 메서드 설명
    • CREATE: 동일한 내용의 노드가 있더라도 생성함
    • MERGE: 동일한 노드가 있다면 무시하고 진행함
  • 쿼리 문에 들어갈 파라미터들은 Prepared 하게 런타임에서 주입
    • Golang에서는 map 에 담아서 사용
CREATE 
(p:Person {name: $name, age: $age, languages: $languages})-[l:LIKES]->(t:Technology {name: $tech})

MERGE 
(p:Person {name: $name, age: $age, languages: $languages})-[l:LIKES]->(t:Technology {name: $tech})

// 각각 노드 생성하고 관계 추가
MERGE (a:Person {name: $name})
MERGE (b:Person {name: $friend})
MERGE (a)-[friendship:KNOWS {since: $friendsSince}]->(b)

// Golang
queryArguments := map[string]interface{}{
    "name": name,
    "age": age,
    "languages": languageList,
    "tech": techName,
}

queryErr := dbCon.Insert(CreatePersonQuery, queryArguments)

Select(Match)

  • ExecuteQuery 로 쿼리 수행하고, 나온 데이터를 핸들링한다.
    • []*db.Record 타입으로 리턴됨
내가 핸들링한 방법
  • dbtype.node 의 Props로 감싸고, 키 값으로 처리
  • 공식문서는 AsMap()으로 처리
// ============== 내가 한 방식 ==============
for _, record := range result {
    person, isPersonExist := record.Get("p")

    if !isPersonExist {
        log.Printf("[SINGLE_PERSON] No Person Data Found: %v", isPersonExist)
        continue
    }

    log.Printf("[SINGLE_PERSON] Get single person: %v", person)

    personProperties := person.(dbtype.Node).Props

    personData := Person{
        Name: personProperties["name"].(string),
        Age: personProperties["age"].(string),
        Languages: personProperties["languages"].([]string),
    }

    personList = append(personList, personData)
}

// ============== 공식문서 ==============
 if employeesN := org.AsMap()["employeesN"].(int64);
       employeesN < employeeThreshold {
        err = addPersonToOrganization(ctx, tx, name, orgId)

        if err != nil {
            return nil, err
            // Transaction will roll back
            // -> not even Person is created!
        }
    }
728x90
반응형

'백엔드 Backend > Golang' 카테고리의 다른 글

[gRPC] Go 언어로 gRPC 사용해보기  (2) 2024.12.24
[Neo4J] 데이터 핸들링하기  (1) 2024.12.09
[Neo4j] Golang으로 Neo4j 연동  (0) 2024.12.05
[GO] Ubuntu 서버에 설치  (1) 2024.10.30
[GO] Goroutine이란?  (0) 2024.10.02
728x90
반응형

공식 문서

Golang으로 연결

  • neo4j 드라이버 설치
    • 연결의 인증은 여러 방식이 있음; BasicAuth, BearerAuth, AuthToken, CustomAuth, ...
    • 본 예시는 유저 이름과 패스워드로 인증하는 방식
go get -u github.com/neo4j/neo4j-go-driver/v5/neo4j
  • 드라이버 인스턴스 생성
import (
    "github.com/neo4j/neo4j-go-driver/v5/neo4j"
    "github.com/neo4j/neo4j-go-driver/v5/neo4j/db"
)

func main() {
    driver, err := neo4j.NewDriverWithContext(
        "neoj4://<DATABASE_URI>:<DATABASE_PORT>,
        neo4j.BasicAuth(<USER>, <PASSWD>, ""),
    )
}
  • 연결 체크
import (
    "context"

    "github.com/neo4j/neo4j-go-driver/v5/neo4j"
    "github.com/neo4j/neo4j-go-driver/v5/neo4j/db"
)

func main() {
    driver, err := neo4j.NewDriverWithContext(
        "neoj4://<DATABASE_URI>:<DATABASE_PORT>,
        neo4j.BasicAuth(<USER>, <PASSWD>, ""),
    )

    ctx := context.Background()

    err := driver.VerifyConnectivity(ctx)

    if err != nil {
        log.Printf("[GRAPH_DB] Check Connection Error: %v", err)
        return err
    }

    defer driver.Close(ctx)

    return nil
}

Golang으로 쿼리

  • 쿼리 실행
    • ExecuteQuery 메서드로 쿼리 실행
import (
    "context"

    "github.com/neo4j/neo4j-go-driver/v5/neo4j"
    "github.com/neo4j/neo4j-go-driver/v5/neo4j/db"
)

func main() {
    driver, err := neo4j.NewDriverWithContext(
        "neoj4://<DATABASE_URI>:<DATABASE_PORT>,
        neo4j.BasicAuth("<USER>", "<PASSWD>", ""),
    )

    ctx := context.Background()

    // 쿼리 실행
    result, queryErr := neo4j.ExecuteQuery(
        ctx, 
        driver, 
        "MERGE (n:Node {name:"$nodeName"})", // Node라는 유니크 노드 생성
        []map[string]interface{ // 파라미터 생성. nodeName에 들어갈 값
            nodeName: "New Node"
        }, 
        neo4j.EagerResultTransformer, // 쿼리 결과 변환
        neo4j.ExecuteQueryWithDatabase("neo4j"),
    )

    if queryErr != nil {
        return nil, queryErr
    }

    defer db.Close(ctx)

    for _, record := range result.Records {
        log.Printf("[GRAPH_DB] Query Result: %v", record.Values...)
    }

    // 쿼리 결과에 대한 요약
    log.Printf("The query `%v` returned %v records in %+v.\n",
        result.Summary.Query().Text(), len(result.Records),
        result.Summary.ResultAvailableAfter())
}
728x90
반응형

'백엔드 Backend > Golang' 카테고리의 다른 글

[gRPC] Go 언어로 gRPC 사용해보기  (2) 2024.12.24
[Neo4J] 데이터 핸들링하기  (1) 2024.12.09
[Neo4j] Golang 으로 쿼리 핸들링  (0) 2024.12.06
[GO] Ubuntu 서버에 설치  (1) 2024.10.30
[GO] Goroutine이란?  (0) 2024.10.02
728x90
반응형
  • 아래는 쿼리문이 아니라 표현식이다.

(:nodes)-[:ARE_CONNECTED_TO]->(:otherNodes)
  • () 기호는 노드를 의미함
  • -[]-> 는 노드 간의 관계를 의미함
  • 각 노드와 관계에 대해 properties를 할당함
  • 노드들은 특정 라벨에 의해 그룹화 될 수 있음
    • 라벨은 테이블, 노드는 레코드라고 생각할 수 있음

노드 변수

  • SQL의 Alias라고 생각하면 됨.
    • 즉 쿼리에서의 변수 선언
  • 노드 앞에 : 가 없다면 그 자체가 변수가 되어버림
    • 이건 관계에서도 동일함
// 변수 없을 때
MATCH (:Person)
Return Person


// 변수 있을 때
MATCH (p:Person)
RETURN p

// 변수만 돌려줌
MATCH (Person)
RETURN Person

관계

  • 관계는 언제나 화살표로 방향을 가지고 있음
  • 방향이 선언되지 않은 경우 MATCH 구문을 사용함
    • 방향이 특정되지 않았다는 것은, 어느 방향으로든 가능하다는 의미
  • 아래 예시는 쿼리문이 아니라 설명임
  • // 오른쪽 방향 [p:Person]-[:LIKES]->(t:Technology)

// 왼쪽방향
[p:Person]<-[:LIKES]-(t:Technology)

// 방향 없을 때
(p:Person)-[:LIKES]-(t:Technology)


### 관계 타입
* 관계 타입은 자연어 처럼 노드들이 서로 관계하는지를 알려준다
* 관계 타입은 **관계들을 카테고리 화** 시킨다.
    * 이는 라벨이 노드들을 하나로 묶는것과 비슷한 역할
* 또한 노드들이 서로 어떻게 관계하는지를 설명한다

```cypher
MATCH (p:Person)-[r:LIKES]->(t:Technology)
RETURN p,r,t

다양한 관계들

  • 관계라는게 매개 테이블 처럼 생각하면 될 것 같다.

CREATE
  (alice:Person {name:'Alice', age: 38, eyes: 'brown'}),
  (bob:Person {name: 'Bob', age: 25, eyes: 'blue'}),
  (charlie:Person {name: 'Charlie', age: 53, eyes: 'green'}),
  (daniel:Person {name: 'Daniel', eyes: 'brown'}),
  (eskil:Person {name: 'Eskil', age: 41, eyes: 'blue'}),
  (alice)-[:KNOWS]->(bob),
  (alice)-[:KNOWS]->(charlie),
  (bob)-[:KNOWS]->(daniel),
  (charlie)-[:KNOWS]->(daniel),
  (bob)-[:MARRIED]->(eskil)

Properties

  • 노드와 관계 모두에 추가될 수 있는 데이터 타입들
  • properties는 {key: 'value'} 로 담는다
// 프로퍼티 생성
CREATE (p:Person {name:'Sally'})-[r:IS_FRIENDS_WITH]->(p:Person {name:'John'})
RETURN p, r

// 이건 쿼리가 아님
(p:Person {name: "Sally"})-[r:LIKES]->(g:Technology {type: "Graphs"})

쿼리문

// 생성
CREATE (p:Person {name: "Sally"})-[r:LIKES]->(t:Technology {type: "Graphs"})

// 조회
MATCH (p:Person {name: "Sally"})-[r:LIKES]->(t:Technology {type: "Graphs"})
RETURN p,r,t

// 조회
MATCH (p:Product)
RETURN p.productName, p.unitPrice
ORDER BY p.unitPrice DESC
LIMIT 10;

// WHERE 문 이용한 조회
MATCH (p:Product)
WHERE p.productName = 'Chocolade'
RETURN p.productName, p.unitPrice;

// properties 조회
MATCH (p:Product {productName:'Chocolade'})
RETURN p.productName, p.unitPrice;

// IN 이용한 조회
MATCH (p:Product)
WHERE p.productName IN ['Chocolade','Chai']
RETURN p.productName, p.unitPrice;

// LIKE 이용한 조회
MATCH (p:Product)
WHERE p.productName STARTS WITH 'C' AND p.unitPrice > 100
RETURN p.productName, p.unitPrice;

// 정규식을 이용한 조회
MATCH (p:Product)
WHERE p.productName =~ '^C.*'
RETURN p.productName, p.unitPrice

// JOIN 을 이용한 조회
MATCH (p:Product {productName:'Chocolade'})<-[:ORDERS]-(:Order)<-[:PURCHASED]-(c:Customer)
RETURN DISTINCT c.companyName;

OPTIONAL MATCH

  • optional match는 OUTER JOIN 과 같음
  • MATCH (c:Customer {companyName:'Drachenblut Delikatessen'}) OPTIONAL MATCH (p:Product)<-[o:ORDERS]-(:Order)<-[:PURCHASED]-(c) RETURN p.productName, toInteger(sum(o.unitPrice * o.quantity)) AS volume ORDER BY volume DESC;

인덱싱

CREATE INDEX Product_productName IF NOT EXISTS FOR (p:Product) ON p.productName;
CREATE INDEX Product_unitPrice IF NOT EXISTS FOR (p:Product) ON p.unitPrice;
728x90
반응형
728x90
반응형

NeoJ4 특징

  • https://neo4j.com/docs/getting-started/whats-neo4j/
  • 가장 많이 사용되는 그래프 데이터베이스 중 하나
  • Cypher라는 선언전 쿼리 언어 사용
    • SQL 과 유사함
  • 노드와 관계에 대한 쿼리
  • 클러스터를 형성해서 분산 처리 가능
  • AuraDB는 클라우드 서비스
  • 도커 이미지도 있음
  • 쿠버네티스도 있음

표현식

  • 아래는 Cypher를 이용한 노드 간의 관계를 표현한 내용이다.
(:nodes)-[:ARE_CONNECTED_TO]->(:otherNodes)
  • () 기호는 노드를 의미함
  • -[]-> 는 노드 간의 관계를 의미함
  • 각 노드와 관계에 대해 properties를 할당함
  • 노드들은 특정 라벨에 의해 그룹화 될 수 있음
    • 라벨은 테이블, 노드는 레코드라고 생각할 수 있음
728x90
반응형
728x90
반응형

그래프 데이터베이스

  • 그래프 데이터베이스는 노드 Nodes, 관계 Relationships, 프로퍼티 Properties 로 된 데이터를 저장하는 데이터베이스
  • 개념
    • Node: 그래프에서의 개체 Entity
    • Relationship: 노드 간의 관계에 대한 이름
    • Property: Node 및 Relationship에 대한 속성들
  • RDB와 비교 비유
    • Label은 RDB의 테이블
    • Node는 레코드(Row)
    • Property는 필드(Column)
    • Relationship은 관계. 딱히 대응시킬 개념은 없는듯

사용하는 이유

  • 대량의 복잡한 데이터 핸들링에 용이함
  • 기존 RDB에서 JOIN 연산은 비용이 비쌈
  • 그래프 데이터베이스는 JOIN 연산이 없음
    • 관계를 더 유연한 포맷으로 네이티브하게 저장함으로써, 데이터 조회 비용도 낮추고 속도도 더 빠르게 최적화됨

많이 사용하는 GraphDB

728x90
반응형
728x90
반응형
  • Neo4j Community Edition
    • 가장 많이 쓰이는 그래프 데이터베이스
    • Cypher라는 쿼리 언어 사용
    • 주로 관계 탐색, 소셜 네트워크 분석, 온톨로지 관리에 사용됨
  • ArangoDB Community Edition
    • 다중 모델 데이터베이스
    • 그래프, 문서, 키-값 데이터 모두 관리 가능.
    • AQL (ArangoDB Query Language) 사용하여 그래프 쿼리 실행
    • 복잡한 관계 데이터 모델링, 온톨로지 관리, 문서형 데이터 통합
  • JanusGraph
    • 유연한 그래프 쿼리 작성 가능.
    • 분산형 아케틱처 지원하여 대규모 데이터에서도 효율적
    • Apache TinkerPop의 Gremlin 쿼리 언어를 사용
    • Cassandra, HBase, ScyllaDB 같은 분산 데이터베이스 및 Elasticsearch, Solr 등의 검색 엔진 지원
    • 대규모 그래프 데이터 처리, 소셜 네트워크, 지식 그래프, 온톨로지 관리
  • OrientDB Community Edition
    • 그래프와 문서형 데이터베이스가 결합된 멀티 데이터베이스
    • SQL과 유사한 쿼리 언어 제공
    • 관계형 데이터베이스와 그래프 데이터베이스의 혼합 사용
    • 데이터 분석 및 온톨로지 관리
  • Apache TinkerPop과 Gremlin Server
    • 그래프 프로세싱을 위한 프레임워크로 다양한 DBMS와 함께 사용
    • Gremlin은 복잡한 그래프 탐색에 유용한 쿼리 언어
    • 다양한 그래프 데이터베이스와 연동 가능
    • 그래프 분석, 온톨로지와 지식 그래프 구축
728x90
반응형
728x90
반응형

PostgreSQL 로 온톨로지 DB 구축 시 주의점

  • 다소 복잡할 수 있음

  • 온톨로지 특성상 RDB보다 GraphDB 가 더 적합한 경우가 많음

  • 데이터 스키마 설계

    • 개념 테이블: 온톨로지 개념 저장할 수 있는 테이블
    • 속성 테이블: 각 개념에 포함된 속성을 저장하는 테이블
    • 관계 테이블: 개념 간 관계 테이블
  • JSON 데이터 타입 활용

    • PostgreSQL JSONB 타입 활용
      • JSONB 칼럼에 개념이나 관계에 대한 속성을 넣어 필요에 따라 필드 수정하지 않아도 됨
  • 공통 테이블 표현식(CTE) 및 재귀 쿼리 활용

    • 공통 테이블 표현식(CTE)와 재귀 쿼리 사용하여 계층적 데이터 구조 쿼리
      • 하나의 개념 -> 하위 개념 탐색 쿼리 가능
  • 인덱스 최적화

    • JSONB 필드 사용할 경우, GIN 인덱스 활용
  • PostGIS

    • 지리적 정보 관리
  • SPARQL 및 그래프 DBMS 와 연동

    • PostgreSQL은 SPARQL을 기본적으로 지원하지 않음
    • 외부 SPARQL 엔진과 PostgreSQL 연동
      • PostgreSQL의 데이터를 그래프 데이터베이스에 동기화

장점

  • 기존 온톨로지 관리 소프트웨어보다 속도 및 안정성 활용 가능
  • JSONB와 같은 유연한 데이터 타입을 통해 다양한 데이터 효율적 저장 가능

단점

  • 관계형 DBMS로 그래프처럼 계층적 구조를 구현하고 관리하면 다소 복잡함
  • SPARQL과 같은 온톨로지 전용 쿼리 언어를 직접적으로 사용할 수 없음
    • 따라서 그래프 DBMS와 연동하여 SPARQL 사용하는거네
728x90
반응형
728x90
반응형

온톨로지 데이터베이스

  • 개념과 관계가 체계적으로 정의 및 구조화 된 것
  • 주로 특정 도메인에서의 객체나 개체간의 관계를 나타내는 데이터 구조
  • 자연어 처리, 검색 엔진, 지식 관리 시스템 등에서 많이 사용됨

온톨로지 구성요소

  1. 개념(Entity): 특정 도메인의 주요 항목
    • 차량, 사람, 도로
  2. 속성: 각 개념이 가지는 특성
    • 차량 - 제조사, 모델명
  3. 관계: 개념들 간 연결 및 상호작용
    • '사람'은 '차량'을 '소유'한다
  4. 규칙 및 제약: 개념과 관계에 대한 규칙 정의 -> 데이터의 일관성과 유효성 보장

온톨로지 구조 설계

  • 데이터 모델링: 개념(Entity), 속성, 관계, 규칙 구조화
    • RDF (Resource Description Framework), WOL (Web Ontology Language) 같은 표준 포맷 사용
  • 계층화: 개념을 계층적으로 구성 -> 데이터 구조 명확히 유지
    • 개념의 상하위 관계 정의
    • 특정 개념 그룹화

데이터베이스 및 자료 관리

  • 그래프 데이터베이스: 온톨로지의 관계성 때문에 그래프 DBMS 사용이 효과적
    • 그래프DB: 노드와 엣지 구조를 이용해 개념과 관계를 시각화 및 관리
    • Neo4j, Blazegraph, Amaonze Neptune,...
  • 문서형 데이터베이스: 개념과 관계가 매우 복잡하거나 변화가 잦은 경우 MongoDB 같은 문서형 DB
    • JSON-LD 같은 표준 사용해 문서 형태로 관리
  • 트리플 스토어: RDF 트리플을 저장하는 DBMS
    • RDF, SPARQL 쿼리 지원하여 데이터 추출 및 분석 용이
    • Apache Jena, Virtuoso,...

온톨로지 편집 및 관리 기능 개발

  • CRUD 기능: 개념, 속성, 관계를 생성, 조회, 수정, 삭제 할 수 있는 인터페이스 구현
  • 시각화 도구: 개념 및 관계를 그래프로 시각화하여 사용자 경험 향상
    • 노드-엣지 그래프 동적 생성
    • D3.js, Cytoscape.js 같은 시각화 라이브러리 활용
  • 버전 관리: 온톨로지 버전 관리 기능으로 변경 사항 추적. 필요시 이전 버전으로 롤백
  • SPARQL 쿼리 인터페이스: 사용자나 개발자가 SPARQL 쿼리를 통해 온톨로지 탐색 및 분석
    • SPARQL API 제공하는 것이 유용
728x90
반응형
728x90
반응형

계기

개발 진행 중, 체인 데이터가 깨지는 이슈가 발생하였으나 컨테이너의 health 체크 및 재시동에 이슈가 발생하였음
현재는 본인이 3년전에 세팅한 Docker Swarm 으로 컨테이너 오케스트레이션 중이나, 서비스 고도화로 인한 오케스트레이션해야 할 컨테이너가 다양해지고 많아짐
컨테이너 health 상태 체크 및 정상화에 대한 기능이 필요해짐
서비스 운영시의 서버 문제 발생 및 리소스 문제 대처를 위한 Auto Scaling 기능 역시 필요
이외에 무중단 배포 전략 수행을 위한 옵션 역시 필요함
이를 해결하기 위한 방안에 대하여 고민중, 회사에 제안할 내용의 초안을 작성해본다.


현 상태

  • Docker Swam을 통한 노드 컨테이너 오케스트레이션이 수행되고 있음
    • 오케스트레이션 대상이 블록체인 노드 8개 밖에 없었기에 kubernetes를 사용할 필요가 없어 보였음
  • 그러나 관리 및 오케스트레이션 해야 할 대상이 많고 다양해짐
    • 노드
    • Explorer
    • 어플리케이션들
      • 거래소
      • 지갑
    • DB
    • 게이트웨이
    • 모니터링 시스템
      • 자체 제작 Collector 및 대시보드
      • Prometheus
      • Grafana
  • Auto-Scaling, 리소스 할당에 대한 필요성 대두
  • 무중단 배포 전략 도입의 필요성 확인

제안

  • 컨테이너 오케스트레이터(Orchestrator)를 Kubernetes로 변경
    • 더욱 안정적 시스템 운영
    • Auto Scaling

구상

  • 노드 구성
    • Master
    • Worker Nodes
      • Explorer
      • Chain Nodes - 7 nodes
      • DataBase
      • Monitoring
      • Trade Application
      • Wallet Application
  • Pods 단위
    • Explorer pod
    • Blockchain Nodes pod
    • Database pod
    • Services
      • Trade Application
      • Wallet Application
      • etc...
    • Monitoring pod
      • Prometheus
      • Grafana
      • 자체 제작 Collecter, Dashboard
728x90
반응형
728x90
반응형

계기

최근 새로운 솔루션 개발 및 데모를 위한 과정에서 많은 이슈들을 경험하였다.
이를 과정에서 현 개발 환경 및 서버 환경의 분리가 필요함을 느꼈다.
때문에 회사에 새로운 서버 구성을 제안하기 위한 초안을 정리해 본다.

현 상태

* 개발 서버에서 모든 서비스의 배포와 테스트가 진행되고 있음
* 로컬 환경에서도 개발 서버의 DB를 보며 개발을 진행하고 있으며, 데모 시에 사용하는 DB 역시 개발 서버에서 수행됨
    * 개발 진행 중 테이블 구조를 바꾸는 경우도 발생하여 데모에 이슈를 야기하기도 함
* 따라서 개발서버는 새로운 기능 배포 및 테스트 용도
* QA 서버를 따로 배포하여, 운영 서버와 동일한 환경에서 데모 및 QA 수행이 필요해 보임

제안

* 운영 서버
* 개발 서버
    * 개발 수행 및 기능 테스트를 위한 서버
* QA 서버 (스테이징 서버)
    * 운영서버와 동일한 환경으로 세팅하여, 운영서버 배포 전 QA 용도로 사용
    *  QA 수행 및 데모 시의 문제를 확인함
        * DB 변동에 의한 데모 및 테스트 문제가 여러번 발생함
        * 로컬 환경에서도 개발 서버를 바라보기 때문에 더 문제가 발생
            * 따라서 DB, 서버, 클라이언트, Explorer(blockscout) 등을 배포해 테스트하는 서버 필요
728x90
반응형

+ Recent posts