Datomic вопрос новичка - моделирование связанных фактов, когда один факт изменяется

Если у меня есть клиентский объект, и он переходит с адреса в момент времени t1, который имеет эти факты:

  • address_line_1 = "10 Даунинг Ст"
  • address_line_2 = "Вестминстер"
  • город = "Лондон"

на новый адрес и время 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, например "Move_house" = true, чтобы выразить, что их адрес отличается.

Мои мысли:

  • Вариант 1, кажется, полагается на "знание" того, что было установлено ранее за все время, которое может больше не соответствовать действительности, поэтому вы можете их исключить.
  • Вариант 2 кажется лучшим - но он означает, что определяется больше сеток, чем я ожидал.
  • Вариант 3 кажется противным!

Чужие мысли по этому поводу будут высоко оценены:)

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"}}]]
Другие вопросы по тегам