Datomic新手问题-当一个事实发生变化时对相关事实进行建模

时间:2019-01-22 10:47:25

标签: data-modeling datomic

如果我有一个客户实体,并且他们从具有以下事实的时间t1的地址移走:

  • address_line_1 =“唐宁街10号”
  • address_line_2 =“威斯敏斯特”
  • city =“伦敦”

具有以下事实的新地址和时间t2:

  • address_line_1 =“ 1600 Pennsylvania Ave NW”
  • city =“华盛顿特区”

如何避免从t2开始的地址看起来像这样:

  • address_line_1 =“ 1600 Pennsylvania Ave NW”
  • address_line_2 =“威斯敏斯特”
  • city =“华盛顿特区”

我能想到的选项:

  1. 在t2断言address_line_2 =“”重置或清空它。
  2. 具有地址,因为它是其自己的实体,指向新地址实体的点只有两个事实:在该实体上声明了address_line_1 =“ 1600 Pennsylvania Ave NW”和city =“ Washington DC”。
  3. 在t2声明一个新事实,例如“ moved_house” = true,以表示该地址是不同的。

我的想法:

  • 选项1似乎依赖于“知道”所有时间之前设置的内容,而这可能不再是正确的,因此您可以将其清除。
  • 选项2似乎最好-但确实意味着定义了更多的网络。
  • 选项3似乎很糟糕!

其他人对此的想法将不胜感激:)

1 个答案:

答案 0 :(得分:0)

您可以将选项2用作组件实体。

https://support.cognitect.com/hc/en-us/articles/215581418-Component-Attributes?mobile_site=true

以下是示例:

;; schema
;;
(d/transact conn [{:db/ident      :client/address
                  :db/cardinality :db.cardinality/one
                  :db/valueType   :db.type/ref
                  :db/isComponent true}
                  {:db/ident      :address/line1
                  :db/valueType   :db.type/string
                  :db/cardinality :db.cardinality/one}
                  {:db/ident      :address/country
                  :db/valueType   :db.type/string
                  :db/cardinality :db.cardinality/one}])

;; create a new client with address - 1 Main Street
;;
(d/transact conn [{:db/id         (d/tempid :db.part/user -1)
                  :client/address {:address/line1   "1 Main Street"
                                   :address/country "USA"}}])

;; datomic will return you two entity id.  One is for :client/address
;; and another one for :address/line1 and :address/country
;;
(d/q '[:find (pull ?e [*])
      :where [?e :client/address]]
    (d/db conn))
;; => [[{:db/id 17592186045418, :client/address {:db/id 17592186045419, :address/line1 "1 Main Street", :address/country "USA"}}]]

;; now update its client address to 9 Kings Road.
;;
(d/transact conn [{:db/id          17592186045418
                  :client/address {:address/line1 "9 Kings Road"}}])

;; 17592186045418 will then have a :client/address 
;; pointing to a new entity with the new address
;;
(d/q '[:find (pull ?e [*])
      :where [?e :client/address]]
    (d/db conn))
;; => [[{:db/id 17592186045418, :client/address {:db/id 17592186045421, :address/line1 "9 Kings Road"}}]]