AgensGraph Tutorial
Import, Query, and Modify Graph Data

Before Getting Started!

본 튜토리얼은 사용자들이 AgensGraph에 샘플 데이터를 적재하고 적재된 데이터를 조회하거나 원하는 정보를 추출하는 과정을 따라할 수 있도록 안내하기 위해 제작되었습니다.

본 튜토리얼을 따라 데이터를 적재하고 활용하시려면 반드시 AgensGraph를 먼저 설치하셔야 하며 시각화 도구인 AgensBrowser를 함께 설치해 사용하신다면 더 쉽고 빠르게 샘플 데이터를 이해하고 분석하실 수 있습니다.

AgensGraph에 데이터를 적재하는 방법은 크게 2가지가 존재합니다.

  1. 데이터셋 파일을 AgensGraph로 Import.
  2. AgensGraph 상에서 쿼리를 실행해 데이터를 생성.

이 튜토리얼에서는 데이터셋 파일(CSV)을 AgensGraph로 Import하는 방법을 설명할 것이며, 쿼리로 데이터를 생성하는 방법이 궁금하시다면 Bitnine 홈페이지를 방문해 Basic Cypher and Advanced Cypher 백서를 참조하시기 바랍니다. 이 튜토리얼에서 사용할 데이터셋을 아래 링크를 통해 다운로드하십시오.

본 튜토리얼은 다음과 같이 구성되어 있습니다.

  1. Dataset Overview
  2. What is, and How to Generate Graph Model
  3. Export Dataset from RDB to CSV
  4. Import CSV to AgensGraph
  5. Querying Graph Data
  6. Updating Graph Data
  7. Notes

01. Dataset Overview: Northwind

본 튜토리얼에서는 RDBMS에서 널리 사용되는 샘플 데이터셋인 Northwind 데이터셋을 사용합니다. Northwind 데이터셋은 흔히 관계형 데이터 예제로 사용되지만 그래프 데이터 예제로도 사용할 수 있습니다. Northwind 데이터셋에는 전세계에서 특수 식품을 수입, 수출하는 Northwind Traders라는 가상의 회사가 존재하며 이 회사의 판매 데이터가 들어 있습니다. 본 튜토리얼에서 제공하는 Northwind 데이터셋은 총 11개 테이블, Vertex Label 6개, Edge Label 6개로 구성되어 있으며 고객 91명, 주문이력 830회, 판매된 상품 77가지를 포함하고 있습니다.

데이터셋의 Entity-Relationship Diagram은 아래와 같습니다.

northwind

02. What is, and How to Generate Graph Model

그래프 모델(Graph Model)은 데이터를 Row와 Column으로 구성된 테이블(Table)이 아니라, 점(Node 또는 Vertex)과 점이 선(Link 또는 Edge)로 연결된 형태인 그래프로 구현한 데이터 모델입니다.

테이블을 사용하는 관계형 모델에서 그래프 모델로 전환 시 다음 내용을 참고하십시오.

  • 관계형 모델에서 Row는 그래프 모델에서 Properties를 가진 Vertex 또는 Edge에 해당.
  • 관계형 모델에서 테이블명(Table Name)은 그래프 모델에서 Vertex Label과 Edge Label에 해당.

Northwind 데이터셋의 그래프 모델은 다음과 같습니다.

metadata

그래프 모델과 관계형 모델의 가장 큰 차이 중 하나는 그래프 모델이 관계형 모델과 다르게 현실 모델(비즈니스 모델)을 있는 그대로 반영한다는 점입니다.

관계형 모델은 복잡한 현실 세계의 비즈니스 모델을 가공해 표 형태의 테이블 형식으로 변환합니다.

하지만 현실 세계의 비즈니스 모델은 각 객체(Vertex)간에 관계(Edge)가 맺어진 형태이고, 유사한 객체끼리의 묶음이 그룹(Label)으로 표현되어 있습니다. 그리고 이는 그래프 모델의 데이터 구현 방식과 매우 유사합니다.

03. Export Dataset from RDB to CSV

만약 사용자의 기존 레거시 RDB에 Northwind 데이터셋이 존재하며 이를 AgensGraph에 적재하고 싶다면, RDB에 존재하는 데이터셋을 먼저 CSV로 Export한 다음 이를 AgensGraph에 적재해야 합니다.

사용자의 레거시 RDB에 존재하는 Northwind 데이터셋을 CSV로 Export하려면 다음 쿼리를 사용자의 RDBMS 상에서 실행합니다.

다음 쿼리는 PostgreSQL을 기준으로 작성되었으며 쿼리 결과로 생성되는 CSV 파일은 기본적으로 "D:\northwind\exp\"에 생성됩니다. 쿼리의 정상적인 실행을 위해 사용자는 사용자 환경에 맞게 CSV 파일 생성 디렉토리("D:\northwind\exp\")를 변경해야 합니다.

COPY (SELECT * FROM categories) TO 'D:\northwind\exp\categories.csv' WITH CSV header;             
                              COPY (SELECT * FROM customers) TO 'D:\northwind\exp\customers.csv' WITH CSV header;               
                              COPY (SELECT * FROM employees) TO 'D:\northwind\exp\employees.csv' WITH CSV header;               
                              COPY (SELECT * FROM employee_territories) TO 'D:\northwind\exp\employee_territories.csv' WITH CSV header;    
                              COPY (SELECT * FROM orders_details) TO 'D:\northwind\exp\orders_details.csv' WITH CSV header;           
                              COPY (SELECT * FROM orders) TO 'D:\northwind\exp\orders.csv' WITH CSV header;                  
                              COPY (SELECT * FROM products) TO 'D:\northwind\exp\products.csv' WITH CSV header;                
                              COPY (SELECT * FROM regions) TO 'D:\northwind\exp\regions.csv' WITH CSV header;                 
                              COPY (SELECT * FROM shippers) TO 'D:\northwind\exp\shippers.csv' WITH CSV header;                
                              COPY (SELECT * FROM suppliers) TO 'D:\northwind\exp\suppliers.csv' WITH CSV header;               
                              COPY (SELECT * FROM territories) TO 'D:\northwind\exp\territories.csv' WITH CSV header;          
                              
                              COPY (SELECT * FROM orders
                              LEFT OUTER JOIN orders_details ON orders_details.OrderID = orders.OrderID) TO 'D:\northwind\exp\orders.csv' WITH CSV header;

04. Import CSV to AgensGraph

CSV형태의 데이터셋을 AgensGraph로 Import하려면 AgensGraph FDW(Foreign-Data Wrapper)를 이용해야 합니다.

  1. 먼저, 'file_fdw' extension을 설치합니다.

    CREATE EXTENSION IF NOT EXISTS file_fdw;
  2. 데이터베이스 연결서버를 생성합니다.

    CREATE SERVER northwind FOREIGN DATA WRAPPER file_fdw;
  3. CSV 파일 형태의 데이터셋을 적재할 각각의 Foreign Table을 생성합니다.

    CREATE FOREIGN TABLE categories (
                                                    CategoryID int,
                                                    CategoryName varchar(15),
                                                    Description text,
                                                    Picture bytea
                                              ) 
                                              SERVER northwind
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\categories.csv', delimiter ',', quote '"', null '');
                                              
                                              CREATE FOREIGN TABLE customers (
                                                    CustomerID char(5),
                                                    CompanyName varchar(40),
                                                    ContactName varchar(30),
                                                    ContactTitle varchar(30),
                                                    Address varchar(60),
                                                    City varchar(15),
                                                    Region varchar(15),
                                                    PostalCode varchar(10),
                                                    Country varchar(15),
                                                    Phone varchar(24),
                                                    Fax varchar(24)
                                              ) 
                                              SERVER northwind
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\customers.csv', delimiter ',', quote '"', null '');
                                              
                                              CREATE FOREIGN TABLE employees (
                                                    EmployeeID int,
                                                    LastName varchar(20),
                                                    FirstName varchar(10),
                                                    Title varchar(30),
                                                    TitleOfCourtesy varchar(25),
                                                    BirthDate date,
                                                    HireDate date,
                                                    Address varchar(60),
                                                    City varchar(15),
                                                    Region varchar(15),
                                                    PostalCode varchar(10),
                                                    Country varchar(15),
                                                    HomePhone varchar(24),
                                                    Extension varchar(4),
                                                    Photo bytea,
                                                    Notes text,
                                                    ReportTo int,
                                                    PhotoPath varchar(255)
                                              )  
                                              SERVER northwind 
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\employees.csv', delimiter ',', quote '"', null '');
                                              
                                              CREATE FOREIGN TABLE employee_territories (
                                                    EmployeeID int,
                                                    TerritoryID varchar(20)
                                              ) 
                                              SERVER northwind
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\employee_territories.csv', delimiter ',', quote '"', null '');     
                                              
                                              CREATE FOREIGN TABLE orders_details (
                                                    orderID int,
                                                    ProductID int,
                                                    UnitPrice money,
                                                    Quantity smallint,
                                                    Discount real
                                              ) 
                                              SERVER northwind
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\orders_details.csv', delimiter ',', quote '"', null '');     
                                              
                                              CREATE FOREIGN TABLE orders (
                                                    orderID int,
                                                    CustomerID char(5),
                                                    EmployeeID int,
                                                    orderDate date,
                                                    RequiredDate date,
                                                    ShippedDate date,
                                                    ShipVia int,
                                                    Freight money,
                                                    ShipName varchar(40),
                                                    ShipAddress varchar(60),
                                                    ShipCity varchar(15),
                                                    ShipRegion varchar(15),                         
                                                    ShipPostalCode varchar(10),                         
                                                    ShipCountry varchar(15)                     
                                              )                          
                                              SERVER northwind                         
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\orders.csv', delimiter ',', quote '"', null '');                         
                                                                       
                                              CREATE FOREIGN TABLE products (
                                                    ProductID int,         
                                                    ProductName varchar(40),
                                                    SupplierID int,        
                                                    CategoryID int,        
                                                    QuantityPerUnit varchar(20),
                                                    UnitPrice money,       
                                                    UnitsInStock smallint, 
                                                    UnitsOnorder smallint, 
                                                    ReorderLevel smallint, 
                                                    Discontinued bit       
                                              ) 
                                              SERVER northwind
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\products.csv', delimiter ',', quote '"', null '');
                                              
                                              CREATE FOREIGN TABLE regions (
                                                    RegionID int,
                                                    RegionDescription char(50)
                                              ) 
                                              SERVER northwind
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\regions.csv', delimiter ',', quote '"', null '');     
                                              
                                              CREATE FOREIGN TABLE shippers (
                                                    ShipperID int,
                                                    CompanyName varchar(40),
                                                    Phone varchar(24)
                                              ) 
                                              SERVER northwind
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\shippers.csv', delimiter ',', quote '"', null '');     
                                              
                                              CREATE FOREIGN TABLE suppliers (
                                                    SupplierID int,
                                                    CompanyName varchar(40),
                                                    ContactName varchar(30),
                                                    ContactTitle varchar(30),
                                                    Address varchar(60),
                                                    City varchar(15),
                                                    Region varchar(15),
                                                    PostalCode varchar(10),
                                                    Country varchar(15),
                                                    Phone varchar(24),
                                                    Fax varchar(24),
                                                    HomePage text
                                              ) 
                                              SERVER northwind
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\suppliers.csv', delimiter ',', quote '"', null '');
                                              
                                              CREATE FOREIGN TABLE territories (
                                                    TerritoryID varchar(20),
                                                    TerritoryDescription char(50),
                                                    RegionID int
                                              ) 
                                              SERVER northwind
                                              OPTIONS (FORMAT 'csv', HEADER 'true', FILENAME 'D:\northwind\territories.csv', delimiter ',', quote '"', null ''); 
  4. Graph를 생성한 후 Graph Path를 지정합니다.

    CREATE GRAPH northwind_graph;
                                                    SET graph_path = northwind_graph;
  5. 이제 Vertex를 생성합니다.

    LOAD FROM categories AS source CREATE (n:category=to_jsonb(source));
                                              LOAD FROM customers AS source CREATE (n:customer=to_jsonb(source));
                                              LOAD FROM employees AS source CREATE (n:employee=to_jsonb(source));
                                              create vlabel if not exists "order";
                                              LOAD FROM orders AS source CREATE (n:"order"=to_jsonb(source));
                                              LOAD FROM products AS source CREATE (n:product=to_jsonb(source));
                                              LOAD FROM regions AS source CREATE (n:region=to_jsonb(source));
                                              LOAD FROM shippers AS source CREATE (n:shipper=to_jsonb(source));
                                              LOAD FROM suppliers AS source CREATE (n:supplier=to_jsonb(source));
                                              LOAD FROM territories AS source CREATE (n:territory=to_jsonb(source));
                                              
  6. 빠른 그래프 탐색을 위해 Vertex의 Index를 생성합니다.

    CREATE PROPERTY INDEX ON category(categoryid);
                                              CREATE PROPERTY INDEX ON customer(customerid);
                                              CREATE PROPERTY INDEX ON employee(employeeid);
                                              CREATE PROPERTY INDEX ON "order"(orderid);
                                              CREATE PROPERTY INDEX ON product(productid);
                                              CREATE PROPERTY INDEX ON region(regionid);
                                              CREATE PROPERTY INDEX ON shipper(shipperid);
                                              CREATE PROPERTY INDEX ON supplier(supplierid);
                                              CREATE PROPERTY INDEX ON territory(territoryid);
                                              
  7. Vertex간의 관계를 생성합니다.

    LOAD FROM orders_details AS source
                                              MATCH (n:"order"),(m:product)
                                              WHERE n.orderid=to_jsonb((source).orderid)
                                                    AND m.productid=to_jsonb((source).productid)
                                              CREATE (n)-[r:ORDERS {unitprice:(source).unitprice,quantity:(source).quantity,discount:(source).discount}]->(m);
                                              
                                              MATCH (n:employee),(m:employee)
                                              WHERE m.employeeid=n.reportto
                                              CREATE (n)-[r:REPORTS_TO]->(m);
                                              
                                              MATCH (n:supplier),(m:product)
                                              WHERE m.supplierid=n.supplierid
                                              CREATE (n)-[r:SUPPLIES]->(m);
                                              
                                              MATCH (n:product),(m:category)
                                              WHERE n.categoryid=m.categoryid
                                              CREATE (n)-[r:PART_OF]->(m);
                                              
                                              MATCH (n:customer),(m:"order")
                                              WHERE m.customerid=n.customerid
                                              CREATE (n)-[r:PURCHASED]->(m);
                                              
                                              MATCH (n:employee),(m:"order")
                                              WHERE m.employeeid=n.employeeid
                                              CREATE (n)-[r:SOLD]->(m);
                                              

위 과정을 모두 정상적으로 수행하셨다면 아래와 같은 그래프 모델이 생성됩니다. (그래프 레이아웃에 따라 보여지는 모습이 달라질 수 있습니다)

browser-sample

05. Querying Graph Data

AgensGraph에 Northwind 데이터 적재가 완료되었다면 Cypher 쿼리로 데이터를 조회하여 데이터가 정상적으로 적재되었는지 확인하며 AgensBroswer에서 쿼리를 실행해 그래프를 시각화해볼 수 있습니다.

  1. 전체 데이터 중 100개를 조회해보기 : 고객, 주문, 상품을 합쳐 최대 100개의 객체를 조회해보겠습니다.

    MATCH path=(c:customer)-[:purchased]->(o:"order")-[r:orders]->(p:product) 
                                                    RETURN path
                                                    LIMIT 100;
  2. 특정 고객의 데이터만 조회해보기 : 여러 고객 중 'Anton'이라는 이름을 가진 고객의 구매 데이터를 조회해보겠습니다.

    MATCH path=(c:customer)-[:PURCHASED]->(o:"order")-[:ORDERS]->(p:product)-[:PART_OF]->(:category)
                                                    WHERE c.customerid = 'ANTON' 
                                                    RETURN path
                                                    LIMIT 100;
  3. 고객별 상품 구매순위 만들기 : 고객이 주문한 상품이 얼마나 자주 구매되었는지 파악하기 위해 상품별 주문율인 rating을 계산해보겠습니다.

    DROP ELABEL IF EXISTS RATED;
                                                    CREATE ELABEL IF NOT EXISTS RATED;
                                                    
                                                    MATCH (c:customer)-[:PURCHASED]->(o:"order")-[:ORDERS]->(p:product)
                                                    WITH c, count(p) AS total
                                                    MATCH (c)-[:PURCHASED]->(o:"order")-[:ORDERS]->(p:product)
                                                    WITH c, total, p, count(o) AS orders
                                                    WITH c, total, p, orders, orders*1.0/total AS rating
                                                    MERGE (c)-[rated:RATED {total_count: to_jsonb(total), order_count: to_jsonb(orders), rating: rating}]->(p);
                                                    

    위 쿼리를 통해 각 상품별 주문율을 뜻하는 rating vertex를 생성했다면 이제 Anton이라는 고객이 주문한 상품과 각 상품에 대한 주문율을 계산할 수 있습니다.

    MATCH path = (c:customer)-[r:RATED]->(p:product)
                                                    WHERE c.customerid='ANTON'
                                                    RETURN c.customerid as cid, r.total_count, p.productName, r.order_count AS ord_cnt, r.rating, path
                                                    ORDER BY cid, ord_cnt DESC
                                                    LIMIT 100;
                                                    

06. Updating the Graph

그래프 데이터를 정상적으로 조회할 수 있었다면 이번에는 그래프 데이터를 업데이트하는 쿼리를 수행합니다. 그래프 데이터를 업데이트 하기 위해 필요한 정보를 찾고 기존 객체의 값을 업데이트 하거나 그래프를 확장할 수 있습니다.

다음은 사원 Janet의 보고대상(REPORTS_TO)을 관리자인 Steven으로 지정하는 쿼리입니다. 먼저 MATCH 쿼리를 통해 Steven Vertex를 찾고, Janet의 기존 보고체계를 나타내는 패턴을 찾습니다. 이 패턴에서 기존의 'REPORTS_TO' edge를 삭제하고, Janet과 Steven 사이에 'REPORTS_TO' edge를 새로 생성합니다.

MATCH (mgr:Employee {EmployeeID:5}) -- Steven (Vertex)
                                    MATCH (emp:Employee {EmployeeID:3})-[rel:REPORTS_TO]->() -- Janet (Vertex) and Her/His REPORTS_TO (Edge)
                                    DELETE rel
                                    CREATE (emp)-[:REPORTS_TO]->(mgr)
                                    RETURN *;

AgensGraph에서는 이렇게 위와 같은 방법으로 그래프를 변경할 수 있습니다. Northwind 데이터셋에 대해 궁금한 점이 있으시거나 AgensGraph를 더 자세히 알고 싶으시다면 아래 링크를 참고해주시기 바랍니다.

Related Links

Additional Dataset

위 튜토리얼 내용으로 데이터를 적재하고 적재된 데이터를 조회, 수정하는 방법을 익히셨다면 다음 IMDB(영화정보) 데이터셋.을 비트나인 깃허브에서 다운받아 활용해보실 수 있습니다.