iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0

讀者也許有聽過 GraphQL 這一類的圖學查詢語言,甚至也有使用過 GraphQL 。如果很喜歡 GraphQL 提供的圖學語意的話,Datomic 的 Pull API 想必可以讓你覺得一見如故。

先看一個範例:『找出齊柏林飛船 (Led Zeppelin) 的團體名稱、與它們開始的年代』

(d/pull db
        '[:artist/name :artist/startYear]
        led-zeppelin)

;; 結果
;; =>  #:artist{:name "Led Zeppelin", :startYear 1968}

這邊使用的是 Datomic 的 Pull API ,它有三個輸入引數:

  1. db 是資料源變數,通常指向資料庫。
  2. '[:artist/name :artist/startYear] 則是模式 (pattern)。
  3. led-zeppelin 是資料實體編碼 (entitiy ID)。

Pull API 示意圖

假設在資料庫內的資料關系,如上圖所示。那如果我們想要找出:「資料實體 A 含有的三個屬性 x, y, z 的值」

(d/pull db
        '[:x :y :z]
        entity-id-A)

遞迴查詢

接續上個例子,由於屬性 z 的值,恰好又是另一個資料實體的實體編碼,所以我們可以將查詢往下再走一層,於是我們在模式 (pattern) 裡,將 :z 改成 {:z [:db/id :q]}。其中,:db/id 對應的值會是資料實體 z 的實體編碼。

如下的查詢就可以取出 entity-id-A 含有的 x, y 屬性值,並且向下遞迴也一併取出資料實體 z 內含的 q 與 db/id 的屬性值。

(d/pull db
        '[:x :y 
          {:z [:db/id :q]}]
        entity-id-A)

所有屬性

有的時候,我們會想要查出,特定資料實體的所有屬性,這可以用萬用字元 (wildcard) 這樣子的模式來比對。

;; What does led-zeppelin have?

(d/pull db '[*] led-zeppelin)

;; 結果
;; => {:artist/sortName "Led Zeppelin",
       :artist/name "Led Zeppelin",
       :artist/type #:db{:id 70746976177619070, :ident :artist.type/group},
       :artist/country #:db{:id 47850746040811801, :ident :country/GB},
       :artist/gid #uuid "678d88b2-87b0-403b-b63d-5da7465aecc3",
       :artist/endDay 25,
       :artist/startYear 1968,
       :artist/endMonth 9,
       :artist/endYear 1980,
       :db/id 2458507999719892}

逆向查詢

Pull API 可以很自然、順暢地表達「包含」的語意。另一方面,也有的時候,Pull API 的第三個引數的資料實體編碼,它會被其它的資料實體包含。這種時候,我們可以在屬性上加上底線 (underscore) 來表現『逆向查詢』,以查出『包含』第三引數的資料實體。

此處 :release/_artists 這個屬性就是由 :release/artists 加上底線得到的。注意一下,底線是要加在 / 的右邊。

(d/pull db '[* :release/_artists] led-zeppelin)

;; 結果
;; => {:artist/sortName "Led Zeppelin",
       :artist/name "Led Zeppelin",
       :artist/type #:db{:id 70746976177619070, :ident :artist.type/group},
       :artist/country #:db{:id 47850746040811801, :ident :country/GB},
       :artist/gid #uuid "678d88b2-87b0-403b-b63d-5da7465aecc3",
       :artist/endDay 25,
       :artist/startYear 1968,
       :artist/endMonth 9,
       :release/_artists
       [#:db{:id 12591607161327185}   ;; ----.
        #:db{:id 13611953951903311}   ;;     | 
        #:db{:id 14614708556444205}   ;;     | 
        #:db{:id 20349761206917151}   ;;     | 
        #:db{:id 27505382880490028}   ;;     | 
        #:db{:id 30606005670815267}   ;;     | 
        #:db{:id 36437815344539172}   ;;     | 
        #:db{:id 38834750693087262}   ;;     | 
        #:db{:id 43703388180886059}   ;;     |-- Releases
        #:db{:id 43910096366902013}   ;;     | 
        #:db{:id 45994770413170389}   ;;     | 
        #:db{:id 49236130691853680}   ;;     | 
        #:db{:id 51514318784597586}   ;;     | 
        #:db{:id 54157544737773785}   ;;     | 
        #:db{:id 58683134597703205}   ;;     | 
        #:db{:id 66718365573484112}   ;;     | 
        #:db{:id 71402285107818196}], ;; ----' 
       :artist/endYear 1980,
       :db/id 2458507999719892}

其它資源

  1. 歡迎訂閱 PruningSuccess 電子報,主要談論軟體開發、資料處理、資料分析等議題。
  2. 歡迎加入 Clojure 社群

上一篇
先從 Datalog 談起 -- part 14 (subqueries)
下一篇
阻抗不匹配與 Datomic 的解決方案
系列文
Datomic,內建事件溯源的資料庫。30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言