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 = "Вашингтон, округ Колумбия"
Варианты, которые я могу придумать:
- подтвердите тот факт, что в момент t2 address_line_2 = "" сбросьте или очистите его.
- иметь адрес как свою собственную сущность, указывать на новую адресную сущность, которая имеет только два факта: address_line_1 = "1600 Pennsylvania Ave NW" и city = "Washington DC", заявленные на ней.
- Утвердите новый факт в момент времени 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"}}]]