在前幾天介紹 Datalog 的範例裡,有一些特殊語法,讀者可能會相當困惑,這邊要來做詳細討論。
:find
子句裡的 [變數 ...]
。參考 Day12
[:find [(pull ?e [:person/name
:movie/_cast]) ...]
:where
[?e :person/name]]
上述的查詢中的 [(pull 變數 模式) ...]
,先忽略使用 pull
語法,[變數 ...]
的部分是一種 :find
子句的規範,又稱之為尋找規範 (find specification)
:find
子句裡的 變數 .
。參考 Day14
(d/q '[:find (sum ?heads) .
:in [[_ ?heads]]]
monsters)
這個查詢也是一樣,變數 .
也是一種尋找規範。
在 SQL 資料庫,一切的資料都只有一種交換的形式:表格。因為 SQL 查詢的輸出統一是表格的形式,也因此,SQL 要透過子查詢 (sub query) 來組裝也變得相當容易。
比方說,如果我們要用 SQL 來產生一個從 1 到 10 的數字,此處的輸出並不是陣列,而是一張只有一個欄位 (column) 的表 (table)。
SELECT generate_series(1, 10) AS num_series;
;; =>
num_series
------------
1
2
3
4
5
6
7
8
9
10
在 Datalog 的話,資料無論是輸入或是輸出,都可以使用四種形式:
以下是四種尋找規範的範例:(註1)
;; single scalar find spec
(d/q '[:find ?v .
:where [0 :db/ident ?v]]
db)
;; 輸出單一的值
;; => :db.part/db
;; single tuple find spec
(d/q '[:find [?e ?ident]
:where [?e :db/ident ?ident]]
db)
;; 輸出單一數組
;; => [106 :session/published?]
;; collection find spec
(d/q '[:find [?v ...]
:where [_ :db/ident ?v]]
db)
;; 輸出陣列
;; =>
[:db.sys/reId
:db/code
:tito.registration/reference
:db.entity/preds
:db/fn
...]
;; relation find spec
(d/q '[:find ?e ?v
:where [?e :db/ident ?v]]
db)
;; 輸出數組的陣列
;; =>
#{[106 :session/published?]
[17592186045418 :location.type/depot]
[121 :tito.ticket/email]
[12 :db.install/valueType]
[45 :db/noHistory]
...}
註: