iT邦幫忙

2024 iThome 鐵人賽

DAY 23
0

Datomic 的 schema 比 SQL 資料庫靈活得多,這邊從三個不同的面向來探討靈活性:

  1. 不需要 NULL
  2. 共用欄位綱要
  3. 不需要使用橋接表 (bridge table)

不需要 NULL

如果一張表 people 有三個資料實體,資料實體是三個人的基本資料,只有一個人有職業。

{:name "John"
 :age 55
 :sex "Male"
 :job "Engineer"}

{:name "Mary"
 :age 45
 :sex "Female"}

{:name "Jack"
 :age 20
 :sex "Male"}

在 SQL 資料庫裡,由於每張表的欄位是固定的,如果要記錄這樣子的資料,只有兩種選項:

  1. people 這張表定義四個欄位,並且讓 Mary, Jack 兩個資料實體的 job 欄位都填入 NULL 值。
  2. people 這張表只定義三個欄位 name, age, sex。並且另外定義一張 job 表,並且在 job 表產生一個欄位指向 people 表,日後存取時需要做 join

在 Datomic 裡,綱要的最小單位不是表,而是欄位。這種欄位綱要 (column schema) 又稱之為屬性。以這個例子的話,Datomic 可以定義如下的欄位綱要。

(def schema
  [{:db/ident       :people/name
    :db/valueType   :db.type/string
    :db/cardinality :db.cardinality/one}

   {:db/ident       :people/age
    :db/valueType   :db.type/long
    :db/cardinality :db.cardinality/one}

   {:db/ident       :people/sex
    :db/valueType   :db.type/long
    :db/cardinality :db.cardinality/one}
    
   {:db/ident       :people/job
    :db/valueType   :db.type/string
    :db/cardinality :db.cardinality/one}])

資料實體在 Datomic 裡,可以想象成像是用程式語言裡的字典結構來儲存,如果缺了特定的欄位,就是讓那個屬性不存在,不需要使用 NULL 值。

共用欄位綱要

如果我們定義了一個 Datomic 屬性 (即欄位綱要),它代表了一個資料實體開始的時間,它可以定義成:

{:db/ident       :time/start
 :db/valueType   :db.type/instant
 :db/cardinality :db.cardinality/one}

我們可以把這個欄位綱要,套用到 people 表以表示人的生日;也可以套用到 car 表以表示汽車的購入時間。一旦這麼做之後,如果日後我們想找出,比某一天 date 更早的所有資料實體,我們就可以使用下列 Datalog 查詢找出來。無論是人或是車都可以一次找出。

[:find ?e
 :in $ ?date
 :where [?e :time/start ?t]
        [(< ?t ?date)]

不需要使用橋接表 (bridge table)

在 SQL 資料庫,當我們需要建模 (model) 多對多的關係 (many to many relationships) 時,我們往往必須設計一張橋接表 (bridge table) 。

在 Datomic 資料庫,我們不需要做這件事,因為我們可以把 :db/cardinality 設定成 :db.cardinality/many ,意思是:這個欄位綱要它可以『一對多』。如果有使用過圖學資料庫,比方說 neo4j ,的讀者,可以想象成 Datomic 允許你定義『邊』(edge)。

其它資源

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

上一篇
as-of 查詢
下一篇
Datomic 的寫入
系列文
Datomic,內建事件溯源的資料庫。30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言