datomic:transact函数并没有真正写入数据库

时间:2016-05-23 05:49:16

标签: clojure datomic

我在无数据组件

中运行dev db

但是,我认为它会向数据库写一些东西但是当我做拉动时,它就不存在了。这是我的peer.clj

(ns dank.peer
  (:require [datomic.api :as d :refer (q)]
            [clojure.pprint :as pp]))

; Name the database as a uri
(def uri "datomic:mem://dank")

; Read the schema and seed data as strings
(def schema-tx (read-string (slurp "resources/dank/schema.edn")))
(def data-tx (read-string (slurp "resources/dank/seed-data.edn")))

; Initialize the db with above vars
(defn init-db
  []
  (when (d/create-database uri)
    (let
      [conn (d/connect uri)]
      @(d/transact conn schema-tx)
      @(d/transact conn data-tx))))

(init-db)

(def conn (d/connect uri))
(def db (d/db conn))

(defn create
  "Creates a new note"
  [notes]
    @(d/transact
      conn
      [{:db/id #db/id[:db.part/user]
        :item/author "default"
        :item/notes notes}]))

(defn get-notes
  [author]
    (d/pull-many db '[*]
      (flatten (into []
       (q '[:find ?e
            :in $ ?author
           :where
           [?e :item/author ?author]]
          db
          author
         )))))

(create "some note") ---->显示了之前和之后的整个交易数据结构。

(get-notes "default") ---> []它是空的!

我在这里错过了什么吗?

2 个答案:

答案 0 :(得分:6)

mavbozo的回答是正确的,当你打电话给get-notes函数时,你在处理新笔记之前使用了数据库的值。

如果您在(def db (d/db conn))之前再次致电get-notes,您将在数据库中看到新数据。

然而,通常优选避免将连接或数据库作为全局变量处理,因为它防止功能行为严格地从其参数确定。正如您所注意到的,get-notes的行为取决于全局状态中db变量的状态。根据经验,最好将数据库值传递给从数据库查询或提取的函数,并将连接传递给对数据库进行交易或监视数据库状态的函数(参见{{ 3}}有关Datomic数据库的各个值的更多讨论。)

在这种情况下,您的get-notes功能可能类似于:

(defn get-notes
  [db author]
    (d/q '[:find (pull ?e [*])  
           :in $ ?author
           :where
           [?e :item/author ?author]]
          db
          author))

然后您可以通过以下方式调用:

(get-notes (d/db conn) "default")

查询最新版本的数据库。这种方法的优点还在于,您可以使用任何数据库值(即最近的,过去给定时间的一个或历史数据库)调用get-notes

同样,我建议您更改create函数以进行连接,而不是使用全局定义的连接。

就管理连接而言,最好尽可能避免使用全局变量。一些首选选项可能是将连接放入应用程序状态映射或在整个程序中传递的原子(如果适用)。另一个经常使用的好选择是利用Stuart Sierra的组件库(http://docs.datomic.com/best-practices.html#consistent-db-value-for-unit-of-work)来管理连接的生命周期。

答案 1 :(得分:3)

t0,t1,t2表示增加时间t,其中t0在t1之前,t1在t2之前

(d/db conn)在调用时返回datomic数据库的当前快照。

让我们说你在调用t0(def db(d / db conn))。在时间t0,音符是空的。这里的db是db time t0的快照。

然后你在时间t1使用(创建“一些音符”)创建一些东西。在时间t1,音符至少包含1个音符。

然后在时间t2你打电话(get-notes“默认”)。在时间t2,音符至少包含1个音符。

问题是,db内的get-notes仍在t0期间引用数据库快照,即db (def db (d/db conn)) t0 t0 1}}。在get-notes时间,仍然没有笔记。这就是(d/db conn)返回空的原因。

当你查询一个数据库数据库时,你必须指定你要查询的数据库:现在的数据库,昨天的数据库,1小时前的数据库等等。当然,现在很容易获得数据库,只需致电get-notes

我发现将db显式用于查询函数很有用,例如将(defn get-notes [db author] ....)函数声明参数更改为{{1}}。