Closed alex-dixon closed 7 years ago
Following up on registering unique attributes via a list: That'd be a pain. We could allow the identification of unique attributes on the fly if we accept the trade off of having no centralized location where unique attributes would be defined. We can still easily persist to Datomic this way if unique-attribute facts are UI only (":mouse/move" ":mouse/down"). They would not need to be part of the schema for us to garbage collect/maintain truth, and we could easily filter them out before persisting by virtue of them not being in the schema.
Proposing we try the following:
(insert! [:unique :mouse/x 42])
[[_ :mouse/x ?v]]
;;...rule to remove older facts with eid :unique (or whatever we decide)...
We could insert :unique in first position for any vector we receive that is length 2 and keyword first if we would rather insert unique attribute facts as [:mouse/x 42]
. Feedback welcome.
After discussion, we are marking identification of facts by their attribute alone as an enhancement currently not on the roadmap for release. Here's what we plan to support instead and our reasoning behind it:
:mouse/x
as an example. Our current understanding of the problem is that we cannot adequately manage and maintain facts of this type.This leaves us with the following todos:
store-action
macro currently generates unique ids for each fact it inserts into the session. Change so each receives the action id. An important implication here is that store-action
becomes usable only for automatic insertion of transient facts. :action
. Change the rule to accumulate all facts with any eid associated with any action and retract them.However, some questions remain about facts that are in some sense 'global' within UI scope and should survive more than one session, such as :ui/visibility-filter
in the todomvc example. Although this fact is inserted via an action, assigning it a unique id will ensure it persists. The problem is that subsequent insertions of this fact will not participate in our schema maintenance, because a new unique id will have been assigned to the fact being inserted, resulting in two facts. In this case we can maintain one value for the fact if we use the same eid, but for such a case we may want or need some kind of "singleton" designation for the client side schema that allows identification of facts by their attribute only.
The current implementation will maintain one to one relationships by default, so if by convention we insert [:global :ui/visibility-filter :all]
, [:global :ui/visibility-filter :active]
, no further implementation is necessary.
Update:
Transient facts/things formerly called "actions" should be inserted with the eid :transient
. Such facts are removed at the end of every session.
This approach may not be well suited to cases in which we want a fact with a proper eid to be removed at the end of every session. No such case has come up yet. The worst case seems consumers would need to implement a rule that performs the same function as the following:
[?e :thing/transient? true]
[?entity <- (acc/all) :from [?e :all]
=>
(retract! ?entity)
We are having to create excessive schema entries for attributes and marking them as :unique/identity in order to have them be one-to-one. Part of this stems from my misunderstanding of :unique/identity. :)
There's a larger issue, which is that sometimes we want attributes to serve as identifiers. For example, we will probably never care about making the mouse an entity. We end up using :mouse/x :mouse/y as the id and grabbing the values (never the eid). How many cases like these there will be, I'm not sure.
Here's my attempt to define things clearly:
From Datomic's documentation:
What we appear to want and lack is a designation of a unique attribute -- an attribute that always resolves to a single entity. I don't think using Datomic's schema is the right way to go about it. Instead, I would propose we define a function that allows us to specify a vector of attributes that should be maintained according to "unique attribute". A function could take this vector and generate the needed rules to find facts two facts with that attribute and remove the older one. Performance concerns abound with this so let me know if you think it's worth trying.