有了 ETL 資料神器 dbt,表資料秒變 NebulaGraph 中的圖資料

NebulaGraph發表於2023-02-09

本文搭配同主題分享影片閱讀更佳,《多資料來源的資料治理實踐》

如果你裝好某款資料庫產品,比如:分散式圖資料庫 NebulaGrpah,躍躍欲試的第一步是不是就讓它幹活搞資料呢?好的,現在問題來了,如何把相對原始的資料處理、建模並匯入 NebulaGraph 呢?本文是一個端到端的示例演示,從多資料來源聚合資料,清理、利用 dbt 轉換成 NebulaGraph 建模的屬性圖點邊記錄,最後匯入成圖譜的全流程。

構建知識圖譜

現在假設你是一個類似於 Netflix、愛奇藝之類的影片服務提供商,我們需要利用圖資料庫搭建一個 使用者-電影 的知識圖譜,來輔助、支撐影片推薦、問答和推薦理由等常見由圖譜支撐的場景。由於時間的關係,這裡先用我們熟悉的老朋友——圖資料庫 NebulaGraph 來搞定知識圖譜。

一般來說,知識圖譜需要的資料會有不同的資料來源,比如一些公開的 API、數倉中的不同資料庫、靜態檔案。這時候,我們如果要構建知識圖譜,需要以下 3 個步驟:

  1. 分析可能獲取的資料;
  2. 選取關心的關聯關係,圖建模;
  3. 抽取關聯關係,匯入圖資料庫。

資料來源

這裡我們會用到兩個資料來源 OMDBMovieLens

OMDB 是一個開放的電影資料庫,將用來模擬公司內部的業務資料。我們可以獲得的資訊有:

  • 電影
  • 電影的分類
  • 電影中的工作人員,包括:導演、動作指導、演員、後期製作等人員資訊
  • 電影封面、宣傳片等電影資訊

MovieLens 是一個開放的資料集,用來模擬公司內部的使用者資料。我們可以獲得的資訊有:

  • 使用者
  • 電影
  • 使用者對電影的評分互動

圖建模

在之前的文章《基於圖資料庫的推薦系統》 裡我們介紹了推薦系統的圖資料庫基本用法。在那篇文章中,內容過濾側重關注 使用者-->電影電影-->分類電影-->演員電影-->導演 等關係,協同過濾則關注 使用者-->電影 的關係,以及推薦理由服務關注以上所有的關係。

總結起來,我們需要的邊有:

  • watched(rate(double))
  • with_genre
  • directed_by
  • acted_by

結合已有資訊,相對應地將頂點中可能需要被關注的資訊作為屬性,給出點 tag 的初始規劃:

  • user(user_id)
  • movie(name)
  • person(name, birthdate)
  • genre(name)

schema_0

表資料到知識圖譜的對映

有了目標的圖譜結構定義,我們來看看手上的資料如何對映到它。

OMDB 資料

首先是 OMDB 資料,它由很多表組成,比如 all_movies 這張表,儲存了所有的電影、以及它們在不同語言下的名字:

movie_idnamelanguage_iso_639_1official_translation
1Cowboy Bebopde1
1Cowboy Bebopen1
2Ariel - Abgebrannt in Helsinkide0
3Shadows in Paradiseen0
3Im Schatten des Paradiesesde0
3Schatten im Paradiesde1

all_casts 表格中保有所有電影相關的工作人員:

movie_idperson_idjob_idroleposition
11121 1
11113 1
11215Luke Skywalker1
11315Han Solo3
11415Leia Organa2

但是這裡的每一個人的姓名等資訊、以及他/她在電影中任職的職位,則分別在表 job_namesall_people 中:

這裡講解下 job_names 表,1 代表編劇、2 代表製作人。有意思的是,和上表的電影 id 與 name 欄位一樣,job_id 到 name 也是一對多的關係,因為 OMDB 中的資料都是多語言的。

job_idnamelanguage_iso_639_1
1Autorende
1Writing Departmenten
1Departamento de redacciónes
1Département écriturefr
1Scenariuszpl
2Produzentende
2Production Departmenten

下面這張表是 all_people

idnamebirthdaydeathdaygender
1George Lucas1944-05-14\N0
2Mark Hamill1951-09-25\N0
3Harrison Ford1942-07-13\N0
4Carrie Fisher1956-10-212016-12-271
5Peter Cushing1913-05-261994-08-110
6Anthony Daniels1946-02-21\N0

這是在資料來源是表結構、RDBMS 中,是一個很典型的情況,所以對於 movie <-[directed_by]-(person) 這個關係,就涉及了 all_moviesall_castsall_peoplejob_names 四個表格:

  • directed_by

    • 起點 person_id 在 all_casts 之中
    • 終點 movie_id 在 all_casts 之中

      • 條件是 job_id 為 job_names 之中的 “director”
  • movie

    • person_id 在 all_casts 之中
    • 名字來自 all_movies 中按 id 查詢,language 為 “en”
  • person

    • movie_id 在 all_casts 之中
    • name、birthday 在 all_people 之中

所有 OMDB 中我們關心的表的關聯如圖:

modeling_omdb

MovieLens 資料集

上面我們講述了單資料來源的場景,只有單一資料來源、資料表或者數倉的資料。但在真實場景中,我們還需要從其他源頭收取資料,並聚合起來。在本例中,我們還需要從 MovieLens 的資料集中抽取需要的知識。

這裡,涉及到 MovieLens 資料集,我們利用的只有:使用者-->電影,這一條關係。

movies.csv 資料:

movieIdtitlegenres
1Toy Story (1995)Adventure
2Jumanji (1995)Adventure
3Grumpier Old Men (1995)Comedy
4Waiting to Exhale (1995)Comedy

ratings.csv 資料:

userIdmovieIdratingtimestamp
114964982703
134964981247
164964982224

從兩個表的資料預覽似乎可以得出:

  • watched

    • 起點來自於 ratings.csv 中的 userId
    • 終點來自於 ratings.csv 中的 movieId
    • 評分來自於 ratings.csv 中的 rating
  • user

    • 來自於 ratings.csv 中的 userId

然而,細心的你們一定發現 MovieLens 資料集中的 movieId 和來自於 OMDB 中的電影 id 完全是不同的兩套體系。如果我們需要讓它們關聯起來,需要將 MovieLens 裡的 movieId 轉換成為 OMDB 中的電影 id,而它們之間的關聯條件則是電影的標題。

但是,通觀察我們知道:

  1. OMDB 電影中標題是多語言的
  2. MovieLens 中的標題結尾帶有(1995)這樣的年份資訊

所以我們最終的結論為

  • watched

    • 起點來自於 ratings.csv 中的 userId
    • 終點來自於 ratings.csv 中的 movieId,終點要從 movies.csv 中的 title ,在 OMDB 之中查詢,得到 OMDB 的 movie_id。查詢條件為去掉年份,從 OMDB 的英文標題中進行匹配
    • 評分來自於 ratings.csv 中的 rating
  • user

    • 來自於 ratings.csv 中的 userId

現在,這個表格之間的關係如下

modeling_omdb_movielens

對映資料到圖譜(屬性圖)

到這裡小結下,我們需要對多個資料來源中的不同表格(或者表格形式的 CSV 檔案)進行聚合,這樣的對應關係如圖所示:藍色虛線表示圖中頂點的資料資訊來源,粉色虛線表示邊資訊的來源。

schema_mapping_to_graph

此外,我們還要對不同表中個體的 id 進行格式化,比如 user_id,是自增的數字,我們要轉換成全域性唯一的 vertex_id。比較方便的方法是在現有 id 的基礎上增加字串字首,比如 u_

最終,以 user -[watched]-> movie 關係為例,我們可以處理得到這樣的表結構資料:

user_idratingtitleomdb_movie_id
u_15Seven (a.k.a. Se7en)807
u_15Star Wars: Episode IV - A New Hope11
u_15Star Wars: Episode IV - A New Hope10
u_14Mask, The832
u_13Mrs. Doubtfire832

其中每一行記錄中存在三個圖上的結構資訊:

  • user 頂點 id
  • movie 頂點 id
  • watched 邊的 rating 值

資料工具

好的,我們現在已經完成了資料的分析與建模設計,在進入”抽取關聯關係,匯入圖資料庫“環節之前,先介紹一下我們要用到的工具。

”抽取關聯關係“可以簡單認為是 ETL 中的 Extract 和 Transform。本質上就是工程上執行資料對映與轉換的工作,市面上有很多不同風格的工具、開源專案可以做 ETL 這件事。這裡我們用到我個人比較喜歡的工具:dbt

資料轉換利器 dbt

dbt 是一個開源的資料轉換工具,它有非常成熟的社群和生態,可以在大多數主流數倉之中進行高效、可控、高質量的資料轉換工作。無論是臨時的轉換工作(ad-hoc),還是在給定的定時 pipeline 中進行復雜編排,dbt 都可以很好勝任。它的一大特色就是使用 SQL LIKE 語言去描述資料轉換的規則。此外,它還基於 GitOps 可以非常優雅地多人協作、維護超大規模資料團隊裡複雜的資料處理作業。而 dbt 內建的資料測試能力可以很好地控制資料質量,可復現、控制資料問題。

dbt 不僅有許多整合的子專案,還能和像是 Meltano、Airflow、Amundsen、Superset 之類的優秀開源專案有機地結合,形成一整套現代的資料基礎設施體系。對具體實踐感興趣的同學可以閱讀文末「參考資料中」的資料治理實踐。

簡單來說,dbt 是一個 Python 寫的命令列工具。針對不同的專案,我們可以用 dbt 建立特定格式的專案資料夾,它會自帶一個 .yaml 配置檔案。我們要在配置檔案裡指定資料轉換的來源資訊在哪裡,目標在哪裡(處理之後的資料儲存的地方,可能是 PostgreSQL、BigQuery、Spark 等)。在資料來源中,我們用 yaml 檔案和 .sql 檔案一起描述了”從哪裡取哪些資料,如何做變換,輸出什麼“的資訊。

starter-project-dbt-cli

這個截圖就是 dbt 官方檔案中的示例專案中的檔案和配置,可以看到 models/example 裡的資訊就是最核心的資料轉換 transform 的規則,而所有的其他資料都是和這個資料轉換相關的後設資料,這些 dbt 專案檔案非常適合用 git 來進行維護,進行現代、自動化的 DataOps。

NebulaGraph 資料匯入

經過 dbt 對資料進行處理之後,我們可以得到直接對映到不同型別的頂點、邊、及其屬性的表結構的中間資料,它們可以是 CSV 的檔案形式,也可以是數倉中的表,甚至可能是 Spark 中的 DataFrame。而將它們匯入 NebulaGraph 有不同的選擇,可以選資料匯入工具 NebulaGraph ExchangeNebulaGraph ImporterNebulaGraph Spark Connector 的任意一款。

在這裡,用最簡單的 NebulaGraph Importer 作為例子。

NebulaGraph Importer 是一個用 Golang 寫的開源資料工具。它可以編譯成一個單檔案的二進位制,透過預配置的 yaml 格式的檔案,讀取指定 CSV 檔案對映到 NebulaGraph 中點、邊關係資料。

實操

現在,我們來實操下如何利用 dbt + NebulaGraph Importer 進行多資料來源聚合、轉換,再匯入 NebulaGraph 的過程。整個專案的程式碼已經開源,倉庫在 https://github.com/wey-gu/movie-recommendation-dataset 上,歡迎大家參考、共建。

整個實操過程如下:

  • 將源資料簡單清洗、匯入數倉 PostgreSQL(EL)
  • 用 dbt 對資料進行轉換 Transform、匯出為 CSV 檔案
  • 用 NebulaGraph Importer 將 CSV 匯入 NebulaGraph(L)

ETL_dbt_nebulagraph_importer

準備 dbt 環境

dbt 是一個 Python 專案,我們在一個虛擬的 Python 3 環境裡安裝好 dbt 和 dbt-postgres。

python3 -m venv .venv
source .venv/bin/activate
pip install dbt-postgres

建立一個 dbt 專案,並進入到空的專案裡:

dbt init dbt_project
cd dbt_project

看看裡邊的檔案吧:

$ tree .
.
|-- README.md                      # 專案說明 README
|-- analyses
|-- dbt_project.yml                # 專案配置檔案
|-- macros
|-- models                         # transform 來源
|   \-- example
|       |-- my_first_dbt_model.sql # 一個描述瞭如何從後設資料中 SELECT 並處理的規則
|       |-- my_second_dbt_model.sql
|       \-- schema.yml             # 規則檔案的後設資料配置,描述了 sql 規則的屬性
|-- seeds                          # 源資料如果是 CSV 檔案,可以放到 seeds 裡
|-- snapshots
\-- tests

7 directories, 5 files

最後,我們們拉一個容器裡的 Postgres 當做我們這個專案的數倉。如果你已經有各種其他數倉,就不需要這一步了,不過要把專案中的配置檔案作相應的修改,並安裝相應的 dbt 外掛。

docker run --rm --name postgres \
    -e POSTGRES_PASSWORD=nebula \
    -e POSTGRES_USER=nebula \
    -e POSTGRES_DB=warehouse -d \
    -p 5432:5432 postgres

資料下載與預處理

我們把資料放到專案的 raw_data 下吧。

mkdir -p raw_data
cd raw_data

注意,假設 raw_datadbt_proeject 之下:

tree ..
..
|-- README.md
|-- analyses
|-- dbt_project.yml
|-- macros
|-- models
|   \-- example
|       |-- my_first_dbt_model.sql
|       |-- my_second_dbt_model.sql
|       \-- schema.yml
|-- raw_data                       # 新建的目錄
|-- seeds
|-- snapshots
\-- tests

8 directories, 5 files

我們把 OMDB 資料下載之後,再解壓:

wget www.omdb.org/data/all_people.csv.bz2
wget www.omdb.org/data/all_people_aliases.csv.bz2
wget www.omdb.org/data/people_links.csv.bz2
wget www.omdb.org/data/all_casts.csv.bz2
wget www.omdb.org/data/job_names.csv.bz2
wget www.omdb.org/data/all_characters.csv.bz2
wget www.omdb.org/data/movie_categories.csv.bz2
wget www.omdb.org/data/movie_keywords.csv.bz2
wget www.omdb.org/data/category_names.csv.bz2
wget www.omdb.org/data/all_categories.csv.bz2
wget www.omdb.org/data/all_movie_aliases_iso.csv.bz2
bunzip2 *.bz2

然後是 MovieLens 資料集的下載、解壓:

wget https://files.grouplens.org/datasets/movielens/ml-latest-small.zip
unzip ml-latest-small.zip
rm *.zip

在匯入數倉進行轉換 Transform 之前我們做一些資料的預處理,把它們放到 seeds 之下。

# 因為是實驗專案,我們簡單粗暴地去掉帶有轉義的引號的資料,因為它們會被認為是無效字元,處理之後的結果放到 seeds 下邊。
grep -v '\\"' raw_data/all_movie_aliases_iso.csv > seeds/all_movie_aliases_iso.csv
grep -v '\\"' raw_data/all_casts.csv > seeds/all_casts.csv
grep -v '\\"' raw_data/all_characters.csv > seeds/all_characters.csv
grep -v '\\"' raw_data/all_people.csv > seeds/all_people.csv
grep -v '\\"' raw_data/category_names.csv > seeds/category_names.csv
grep -v '\\"' raw_data/job_names.csv > seeds/job_names.csv
# 下邊的檔案無需處理,直接放到 seeds 下邊。
cp raw_data/movie_categories.csv seeds/movie_categories.csv
cp raw_data/movie_keywords.csv seeds/movie_keywords.csv
cp raw_data/all_categories.csv seeds/all_categories.csv
cp raw_data/ml-latest-small/ratings.csv seeds/movielens_ratings.csv
cp raw_data/ml-latest-small/movies.csv seeds/movielens_movies.csv

有了 seeds 下邊的檔案之後,可以用一個命令把他們匯入到數倉裡:

dbt seed

執行過程因數倉而異,用本地的 Postgres 可能要等一會兒才能完成,執行結果大概是這樣的:

$ dbt seed
05:58:27  Running with dbt=1.3.0
05:58:27  Found 2 models, 4 tests, 0 snapshots, 0 analyses, 289 macros, 0 operations, 11 seed files, 0 sources, 0 exposures, 0 metrics
05:58:28  
05:58:28  Concurrency: 8 threads (target='dev')
05:58:28  
05:58:28  1 of 11 START seed file public.all_casts ....................................... [RUN]
...
07:10:11  1 of 11 OK loaded seed file public.all_casts ................................... [INSERT 1082228 in 4303.78s]
07:10:11  
07:10:11  Finished running 11 seeds in 1 hours 11 minutes and 43.93 seconds (4303.93s).
07:10:11  
07:10:11  Completed successfully
07:10:11  
07:10:11  Done. PASS=11 WARN=0 ERROR=0 SKIP=0 TOTAL=11

撰寫 Transform model

我們建立 model 如下:

mkdir models/movie_recommedation
touch models/movie_recommedation/user_watched_movies.sql
touch models/movie_recommedation/schema.yml

這時候 models 中的檔案結構大概是這樣的:

$ tree models
models
\-- movie_recommedation
    |-- user_watched_movies.sql
    \-- schema.yml

這個 model 下邊目前只有一個規則,就是負責處理使用者觀看電影這條邊上資料的 SQL 語句。

我們希望輸出三列,所以 schema.yml 中的內容是:

version: 2

models:
  - name: user_watched_movies
    description: "The edges between users and movies they have watched"
    columns:
      - name: user_id
        description: "user id"
        tests:
          - not_null
      - name: movie_id
        description: "movie id"
        tests:
          - not_null
      - name: rating
        description: "rating given by user to movie"
        tests:
          - not_null

注意,這裡的 tests 的表達是對資料驗證、測試的約束。有了它,我可以用 dbt 輕鬆地對資料質量進行測試、驗收,比如:我們要求這裡的三個欄位都是 not_null

然後,我們來寫 SQL 吧,user_watched_movies.sql

{{ config(materialized='table') }}

/*
 JOIN the movieielens_ratings table with the movieielens_movies table, and removing the movie title tailing the year of release
 */
WITH user_watched_movies AS(
    SELECT moveielens_ratings."userId",
        moveielens_ratings."movieId",
        moveielens_ratings.rating,
        REGEXP_REPLACE(moveielens_movies.title, ' \(\d{4}\)$', '') AS title,
        moveielens_movies.genres AS movielens_genres
    FROM moveielens_ratings
        JOIN moveielens_movies ON moveielens_movies."movieId" = moveielens_ratings."movieId"
)
/* 
 JOIN user_watched_movies table with all_movie_aliase_iso table where language is English
 the join condition is the movie title
 */
SELECT concat('u_',user_watched_movies."userId") AS user_id,
    user_watched_movies.rating,
    user_watched_movies.title,
    all_movie_aliases_iso."movie_id" AS OMDB_movie_id,
    user_watched_movies.movielens_genres
FROM user_watched_movies
    JOIN all_movie_aliases_iso ON user_watched_movies.title LIKE CONCAT(all_movie_aliases_iso.name, '%')
    AND all_movie_aliases_iso.language_iso_639_1 = 'en'

而這個 SQL 做的事情就是綠色圓圈標註的部分:

  • movielens_ratings 中選 user id、movie id、rating、movie title(去掉年份),存成 user_watched_movies 的中間表格

    • movie title 從 movielens_movies JOIN ,透過 movie_id 相同的匹配條件取得
  • user_watched_movies 中選 user id(增加字首 u_)、rating、title、OMDB_movie_id

    • OMDB_movie_id 從 all_movie_aliases_isoJOIN,透過相似的電影姓名匹配 OMDB 電影中英文標題取得
    • 最終的欄位作為輸出

transform_select_joins_user_watched_movies

當然,我們可以在 Postgres 的聯結器中透過增加 LIMIT 快速除錯自己的 SQL 語句。

現在我們來透過 dbt 執行、測試剛剛的規則:

dbt run -m user_watched_movies

之後,我們應該就可以在 Postgres(數倉)中看到我們轉換之後的一個表了。

類似的,如法炮製所有其他部分的 Transform 規則,我們就獲得了這麼多 model 了:

$ tree models
models
\-- movie_recommedation
    |-- acted_by.sql
    |-- directed_by.sql
    |-- genres.sql
    |-- movies.sql
    |-- people.sql
    |-- schema.yml
    |-- user_watched_movies.sql
    \-- with_genre.sql

再對他們分別執行 transform:

dbt run -m acted_by
dbt run -m directed_by
dbt run -m with_genre
dbt run -m people
dbt run -m genres
dbt run -m movies

匯出資料為 CSV

實際上,NebulaGraph Exchange 本身就支援把很多資料來源(Postgres,ClickHouse,MySQL,Hive 等等)匯入 NebulaGraph。只是在這個例子中,我們處理的資料量對於 NebulaGraph 來說非常非常小(只有百萬級別的邊而已),所以使用最輕量級的 NebulaGraph Importer 就足夠了。而 NebulaGraph Importer 能消費的資料只有 CSV 檔案,所以我們把剛才的表都輸出為檔案。

首先,我們進入 Postgres 的 Console,執行 COPY 命令

COPY acted_by TO '/tmp/acted_by.csv'  WITH DELIMITER ',' CSV HEADER;
COPY directed_by TO '/tmp/directed_by.csv'  WITH DELIMITER ',' CSV HEADER;
COPY with_genre TO '/tmp/with_genre.csv'  WITH DELIMITER ',' CSV HEADER;
COPY people TO '/tmp/people.csv'  WITH DELIMITER ',' CSV HEADER;
COPY movies TO '/tmp/movies.csv'  WITH DELIMITER ',' CSV HEADER;
COPY genres TO '/tmp/genres.csv'  WITH DELIMITER ',' CSV HEADER;
-- 對於 user_watched_movies 我們不輸出表頭,因為這個檔案中記錄了兩種點、一種邊,沒法讓 importer 透過約定好的表頭自動匯入,只能透過無表頭的情況下指定第幾列對應什麼欄位
COPY user_watched_movies TO '/tmp/user_watched_movies.csv'  WITH DELIMITER ',' CSV;

再把 Postgres 容器裡的檔案匯入到 to_nebulagraph 這個資料夾裡:

mkdir -p to_nebulagraph
docker cp postgres:/tmp/. to_nebulagraph/

匯入 NebulaGraph

建立 NebulaGraph 叢集

我們可以用 Nebula Up 一鍵拉起一個測試的 NebulaGraph 單機叢集,匯入所需資料:

curl -fsSL nebula-up.siwei.io/install.sh | bash

建立 Schema

首先,我們建立一個叫做 moviegraph 的圖空間。針對前面的建模,建立點邊型別的結構 Schema:

先進入 NebulaGraph 的 Console:

~/.nebula-up/console.sh

再執行如下 DDL(Data Definiation Language):

CREATE SPACE moviegraph(partition_num=10,replica_factor=1,vid_type=fixed_string(32));
:sleep 20
USE moviegraph;
CREATE TAG person(name string, birthdate string);
CREATE TAG movie(name string);
CREATE TAG genre(name string);
CREATE TAG user(user_id string);
CREATE EDGE acted_by();
CREATE EDGE directed_by();
CREATE EDGE with_genre();
CREATE EDGE watched(rate float);
exit

建立 NebulaGraph Importer 配置檔案

這個檔案是一個描述 CSV 檔案和叢集中點邊資料對應關係的 YAML 檔案。詳細的格式可以參考檔案:https://docs.nebula-graph.com.cn/master/nebula-importer/use-importer/,或者影片教程:https://www.bilibili.com/video/BV1ny4y1u7i4

最終的配置檔案我已經為大家寫好了,在 https://github.com/wey-gu/movie-recommendation-dataset/blob/main/nebula-importer.yaml 可以下載得到。

這裡,我們就直接下載我寫好了的配置檔案。注意,這個檔案不應該是 dbt 專案檔案的一部分,所以我們退出目錄,向上一層,把它放到 dbt_proeject 外邊:

cd ..
wget https://raw.githubusercontent.com/wey-gu/movie-recommendation-dataset/main/nebula-importer.yaml

開始匯入

這一步,我們用容器化的 NebulaGraph Importer,避免了安裝的步驟:

docker run --rm -ti \
    --network=nebula-net \
    -v ${PWD}:/root/ \
    -v ${PWD}/dbt_project/to_nebulagraph/:/data \
    vesoft/nebula-importer:v3.2.0 \
    --config /root/nebula-importer.yaml

很快,所有的資料就匯入到 NebulaGraph 之中了。現在,我們可以透過 NebulaGraph Console,執行一些查詢看看結果:

進入 Console:

~/.nebula-up/console.sh

進入圖空間、執行 SHOW STATS

USE moviegraph;
SHOW STATS;

結果:

(root@nebula) [moviegraph]> SHOW STATS;
+---------+---------------+---------+
| Type    | Name          | Count   |
+---------+---------------+---------+
| "Tag"   | "genre"       | 14397   |
| "Tag"   | "movie"       | 20701   |
| "Tag"   | "person"      | 263907  |
| "Tag"   | "user"        | 610     |
| "Edge"  | "acted_by"    | 673763  |
| "Edge"  | "directed_by" | 101949  |
| "Edge"  | "watched"     | 31781   |
| "Edge"  | "with_genre"  | 194009  |
| "Space" | "vertices"    | 299615  |
| "Space" | "edges"       | 1001502 |
+---------+---------------+---------+
Got 10 rows (time spent 1693/15136 us)

透過 NebulaGraph Studio,我們也可以在視覺化介面探索這個圖譜。比如:在其中執行這個查詢,看一下給使用者 u_124 推薦電影 1891 的理由可能是什麼?

FIND NOLOOP PATH FROM "u_124" TO "1891" over * BIDIRECT UPTO 4 STEPS yield path as `p` | LIMIT 20

它的結果是:曾經喜歡的星戰電影的大部分演職人員都也參與了這部同樣是“奧斯卡獲獎”且“經典”的電影。

reasoning_movie

總結

當我們打算把海量資料利用圖資料庫的能力進行知識轉化、洞察分析的時候,往往第一步就是要做多資料來源到圖資料的轉換、處理、建模。對於無從下手的新手們來說,一個可行的思路是從所有的相關資訊出發,去設想最關注的關聯關係,把邊寫出來,然後再羅列可以取得的點、以及需要的點、邊上的屬性。確定了初始的建模之後,就可以利用 ETL 工具把原始的資料清洗、ETL 成點、邊型別的表結構,最後,利用匯入工具匯入 NebulaGraph。

藉助於 dbt,我們可以版本控制、測試、迭代建模與資料轉換,一點點進化、豐富構建的知識圖譜。

參考資料


謝謝你讀完本文 (///▽///)

要來近距離快速體驗一把圖資料庫嗎?現在可以用用 NebulaGraph Cloud 來搭建自己的圖資料系統喲,快來節省大量的部署安裝時間來搞定業務吧~ NebulaGraph 阿里雲端計算巢現 30 天免費使用中,點選連結來用用圖資料庫吧~

想看原始碼的小夥伴可以前往 GitHub 閱讀、使用、(^з^)-☆ star 它 -> GitHub;和其他的 NebulaGraph 使用者一起交流圖資料庫技術和應用技能,留下「你的名片」一起玩耍呢~    

相關文章