這幾個函數能增長一點數據庫結構的可讀性,簡單地省掉一些鍵盤時間:數據庫
;; ============================================== ;; 方便性的處理函數。對於每一個 datomic 程序都有用! (defn assoc-when [m k v] (if v (assoc m k v) m)) (defn attr "用縮略形式建立 schema 中的屬性: 每一個屬性必須有 ident 名稱, type 類型和 doc 文檔. 可選用 :cardinality 指定數量以及 :unique 指定惟一性" [ident type doc & {:keys [cardinality unique] :or {cardinality :db.cardinality/one unique nil}}] (-> {:db/ident ident :db/valueType type :db/doc doc :db/cardinality cardinality :db.install/_attribute :db.part/db} (assoc-when :db/unique unique))) (defn entities "給一組實體 ents 在 part 這個數據庫分區中順序生成臨時 id" [part ents] (map #(assoc %1 :db/id (d/tempid part %2)) ents (iterate dec -1))) (defn ensure-db "在 uri 上創建一個數據庫, 它的結構爲 schema, 若是有種子數據 seed-data, 也記入數據庫." [uri schema & [seed-data]] (d/create-database uri) (when-let [conn (d/connect uri)] (d/transact conn db-schema) (when seed-data (d/transact conn seed-data))))
下面這個數據庫函數是傳統的數據庫上必不可少的:ide
(def seq-id "Transaction 函數. 給 eid 實體構造的 id-field 設置一個順序的 id. 至關於傳統數據庫的 sequence 或者自動增加功能. 要求在數據的種子數據中創建一個實體有 :db/ident (函數中用 next-id 指定), 這個實體有屬性 next-value 來存儲當前的最後 id 值." (d/function {:lang "clojure" :params '[db next-id next-value eid id-field] :code '(let [val (inc (get (d/entity db next-id) next-value 0))] [{:db/id next-id next-value val} {:db/id eid id-field val}])}))
(def db-schema "數據庫結構" (entities :db.part/db [(attr :user/name :db.type/string "用戶名" :unique :db.unique/identity) (attr :product/id :db.type/string "產品號" :unique :db.unique/identity) (attr :product/cashValue :db.type/long "產品的人民幣價值(分)") (attr :order/id :db.type/long "訂單號" :unique :db.unique/identity) (attr :order/user :db.type/ref "下訂單的用戶") (attr :order/product :db.type/ref "訂單所關聯的產品") (attr :order/quantity :db.type/long "產品數量") (attr :orderId/value :db.type/long "順序中下一個訂單")])) (def seed-data "種子數據" (entities :db.part/user [{:db/ident :orderId/next :orderId/value 10000} {:db/ident :nextId :db/doc (-> #'seq-id meta :doc) :db/fn seq-id}]))