[Arango DB] Graph Database – Query 002 – Edge, Set and Array

【前情提要】

在上一回中,我們只集中在同個 Collection 內的資料。那接著,我們就要透過 Edge 找到所有關聯的資料,並透過集合(set)合併或篩選資料。

【重點整理】

  1. 透過 _from 與 _to 屬性取得 Edge 的連結
  2. 集合不帶有排序功能,先排序再結合也會亂掉

【預計內容】

  1. Edge 的指向
  2. 集合(聯集、交集與差集)
  3. 陣列的儲存與刪除

【主要內容】

1. Edge 的指向

回想起 Edge Collection,分別有 _from 與 _to 兩個資料指向資料的 _id,藉由這個屬性,我們也能夠獲取到兩端的資料。那這邊,我先做好了資料的準備,標註兩位朋友的各一幅畫。

GraphQL
LET specified_artist_id = "artist_vertices/366"

FOR e IN artist_edges
    FILTER e._from == specified_artist_id
    LET friend_id = e._to
    LET friend = DOCUMENT(friend_id)

    FOR artwork_edge IN work_edges
        FILTER artwork_edge._from == friend_id
        LET artwork_id = artwork_edge._to
        LET artwork_doc = DOCUMENT(artwork_id)
        RETURN {
            friend: friend.full_name,  
            artwork_name: artwork_doc.name,
            style: artwork_doc.style
        }

可以看到,我們只選到在 Edge 中,某畫家(_from)有關的朋友們(_to)的資料

2. 集合(聯集、交集與差集)

在上方,我們透過 Edge 的關聯打印出某畫家的朋友們的作品。那如果希望將畫家本人的作品也加入進來,又只能回傳一次怎麼辦?這時就可以依靠集合概念中的聯集 UNION,組成 JSON 回傳。

那在範例中,可以看到我們分別用兩個變數,個別儲存作家本人與朋友們的資料,最後才統合資料。最後能看到,我們多出(有登記的)Claude Monet 的三個作品。

GraphQL
LET specified_artist_id = "artist_vertices/366"

LET works_of_artist = (
    FOR e IN work_edges
        FILTER e._from == specified_artist_id
        LET artwork_doc = DOCUMENT(e._to)
        
        RETURN {
            artist: DOCUMENT(specified_artist_id).full_name, 
            artwork_name: artwork_doc.name, 
            style: artwork_doc.style
        }
)

LET works_of_friend = (
    FOR e IN artist_edges
        FILTER e._from == specified_artist_id
        LET friend = DOCUMENT(e._to)
        FOR work_edge IN work_edges
            FILTER work_edge._from == e._to
            LET artwork_doc = DOCUMENT(work_edge._to)
            RETURN {
                artist: friend.full_name,  
                artwork_name: artwork_doc.name,
                style: artwork_doc.style
            }
)

RETURN UNION(works_of_artist, works_of_friend)

而交集是指多個集合中共同擁有的部分。那再來,我們透過所有作品與作家作品來呈現交集,透過 INTERSECTION 從所有作品塞出作家的作品。

GraphQL
LET specified_artist_id = "artist_vertices/366"

LET works_of_artist = (
    FOR e IN work_edges
        FILTER e._from == specified_artist_id
        LET artwork_doc = DOCUMENT(e._to)
        
        RETURN {
            artwork_name: artwork_doc.name, 
            style: artwork_doc.style
        }
)

LET works_of_all = (
    FOR work IN work_vertices
        RETURN {
            artwork_name: work.name,
            style: work.style
        }
)

RETURN INTERSECTION(works_of_artist, works_of_all)

那相對的,差集是指集合中不同的資料。而在 AQL 語法中,則是用相對於交集的 OUTERSECTION 代表。那在下方的範例中,那為了方便證明少去上方的三筆資料,我們直接透過畫作名稱做查詢。

GraphQL
LET specified_artist_id = "artist_vertices/366"

LET works_of_artist = (
    FOR e IN work_edges 
        FILTER e._from == specified_artist_id
        LET artwork_doc = DOCUMENT(e._to)
        RETURN {
            artist_id: artwork_doc.artist_id, 
            artwork_name: artwork_doc.name, 
            style: artwork_doc.style
        }
)

LET works_of_all = (
    FOR work IN work_vertices
        RETURN {
            artist_id: work.artist_id, 
            artwork_name: work.name,
            style: work.style
        }
)

LET set = OUTERSECTION(works_of_artist, works_of_all)

LET sorted_results = (
    FOR result IN set
        SORT result.artist_id ASC 
        RETURN result
)

RETURN sorted_results

那各位應該有看到在上方的最後我依照作家的 ID 逐個重新排序,這是因為先 SORT 再做集合,照集合的整理特性排序很常會亂掉。

3. 陣列的儲存與刪除

在 AQL 中,其針對陣列的增減類似於 JavaScript 的概念,依樣式透過虛擬的資料結構來進行儲存與刪除,也就是常見的 stack 與 queue 型態。

那這邊我們就不使用複雜的資料,用數字陣列方便各位理解概念。那以 stack 的概念,分別有 PUSH (+) 與 POP (-) 兩個方法,是針對陣列的最末端進行處理。類似的道理之下,我們會再用 queue 的概念操作 UNSHIFT (+) 與 SHIFT (-),針對前端做處理。

那依照下方的 PUSH,我們將 4 加入到末端,變成 [1, 2, 3, 4]

GraphQL
RETURN PUSH([1, 2, 3], 4)

此時,我們再透過 POP,剔除剛加入的數字。但不同於一般的程式語言只回傳脫離的 4,為了 query 的完整性,回傳的會是 [1, 2, 3]

GraphQL
RETURN POP([1, 2, 3, 4])

用一樣的架構去呼叫 UNSHIFT,回傳的結果是 [4, 1, 2, 3]

GraphQL
RETURN UNSHIFT([1, 2, 3], 4)

而接著 SHIFT 排序好的陣列,則會變為 [2, 3, 4]

GraphQL
RETURN SHIFT([1, 2, 3, 4])

【後話】

那在這篇中,我們簡單的呈現如何利用 Edge 取得橫跨的資料。並藉由集合與陣列,講述簡單的資料合併方式。那在下一篇,我將以常說的 CRUD 進行資料的增加修改。那麼,我們下期再會。

【參考資料】

[1] Array Function
https://docs.arangodb.com/3.11/aql/functions/array/

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.