【问题标题】:Datomic newbie question - modelling related facts when one fact changesDatomic新手问题 - 当一个事实发生变化时对相关事实进行建模
【发布时间】:2019-01-31 07:22:39
【问题描述】:

如果我有一个客户实体,并且他们在时间 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 以表示 tehir 地址不同。

我的想法:

  • 选项 1 似乎依赖于“了解”以前设置的所有时间可能不再正确的内容,因此您可以将它们排除在外。
  • 选项 2 似乎最好 - 但确实意味着定义的网络比我预期的要多。
  • 选项 3 看起来很糟糕!

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

【问题讨论】:

  • 您也可以使用事务函数收回 address_line_2 datom。
  • 1 或 2 都可以。我更喜欢#2,因为地址是一个独立的“实体”(您通常会将 Address 在 Java 等中作为一个单独的类)。
  • 谢谢 :) 但是我对选项 #1 的评论呢?“选项 1 似乎依赖于“了解”以前设置的内容,这可能不再适用,因此您可以将它们排除在外。 "我的想法比这个地址示例更普遍。选项 #2 似乎更笼统 - 但请参阅下面的评论。

标签: data-modeling datomic


【解决方案1】:

您可以将选项 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"}}]]

【讨论】:

  • 谢谢。我不知道组件实体。我想知道保存时这会是什么样子 - Datomic 如何区分编辑地址中的拼写错误和“移动”到一个全新的地址?让我知道这是否值得它自己的堆栈溢出问题!
  • 如果你使用地图接口,更新事务将被转换为一个retract-and-add。这意味着组件将被新实体替换。
猜你喜欢
  • 2017-02-02
  • 1970-01-01
  • 1970-01-01
  • 2020-02-26
  • 2014-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多