讀者也許有聽過 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 ,它有三個輸入引數:
db
是資料源變數,通常指向資料庫。 '[:artist/name :artist/startYear]
則是模式 (pattern)。led-zeppelin
是資料實體編碼 (entitiy ID)。假設在資料庫內的資料關系,如上圖所示。那如果我們想要找出:「資料實體 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}