Fork me on GitHub

The datomic docs say this: The example below uses retraction to stop retaining history for :person/address.

[[:db/retract :person/address :db/noHistory false]
 [:db/add :db.part/db :db.alter/attribute :person/address]]
- does it really? You retract :db/noHistory false to stop retaining history?


Seems more intuitive to me to add :db/noHistory true, I guess. Maybe this leaks some implementation detail?


I guess it's an error in that doc. A few lines before it says "Altering an attribute's :db/noHistory to false or retracting it will ... start retaining history..." so I would say it's starting to retain history


@magnars the docs are correct there, but require the context of the preceding section. It’s retracting the previous assertion of :db/noHistory false.


I'd like to understand this… isn't false the default value for :db/noHistory?


and since that's the case, why would retracting a fact that states the default cause :db/noHistory to become true?


By my reading, neither the assertion of :db/noHistory false nor the retraction of the same would have any actual effect on the retention of history, given that there's no prior assertion of :db/noHistory true for :person/address.


yeah, that is my intuition as well - it feels decidedly strange the way it is described in this example.


I think the behavior described may actually be incorrect - sorry, investigating further. I’ll update here.


fwiw, I just spent some time exploring in a repl. I can't find any retraction that causes :db/noHistory to become true.


@bhagany: I can confirm that I see the same thing as you (I worked through several changes tracking the outcome in terms of datoms in :tx-data) and can reason fairly simply about why this is the case — I’m verifying expected behavior now before any follow up.


@bkamphaus: I am very relieved that my mental model turns out not to be disastrously wrong simple_smile




@bhagany and @magnars I can confirm that retracting [… :db/noHistory false] will not have the outcome previously stated in the docs (stop retaining history). I've revised the docs at:


Does anyone happen to know of a hashing algorithm that you can use to generate a unique attribute that will index “easily” (a la squuid)?


In my example, I have an entity that is the child of two parents, and the combination of the two parents is unique. (hash-algorithm parent-id-1 parent-id-2) would generate a unique string for my entity.


Basically I want to guarantee my :db.unique/identity attribute is deterministic, but not in a way that harms indexing like SHA1 would.


Or, if not a hashing algorithm, some deterministic strategy that works well with datomic’s indexing.


@potetm: Indexing performs best when new values are always added at or close to the "end" of the index. squuid achieves this by creating a hashed value where the high bits increase over time. But a deterministic hash function cannot do this. I wouldn't worry about it too much unless you have a measurable performance problem. Just generate a string combining unique values from the parents.


@stuartsierra: Awesome. We thought that might work as well. Is there by chance some rule of thumb for an upper limit of items indexed in that way? Or is it basically, “do it until you notice problems”?


@potetm: There is no upper bound that I know of, other than the much-discussed bounds on optimal size of a Datomic database. As always, testing on a production-sized set of your own data is the only way to be sure.


Right. Cool then. Thanks for your help! Much appreciated.


You're welcome


good morning guys. I have a single-attribute entity, which represents a list of items. Each item is an enum value. How can I enforce uniqueness of such single-attribute entity?

;; schema for entity:
[{:db/id #db/id[:db.part/db]
  :db/ident :some-set/items
  :db/valueType :db.type/ref
;  :db/unique :db.unique/value
;  :db/unique :db.unique/identity
  :db/cardinality :db.cardinality/many
  :db/fulltext true
  :db/doc "List of all items included in this set."
  :db.install/_attribute :db.part/db}]

;; enums:
[{:db/id #db/id[:db.part/user] :db/ident :enum/a}
 {:db/id #db/id[:db.part/user] :db/ident :enum/b}
 {:db/id #db/id[:db.part/user] :db/ident :enum/c}]

;; trying to create 2 sets:
'[{:db/id #db/id[:db.part/user -1] :some-set/items [:enum/a :enum/b]}
  {:db/id #db/id[:db.part/user -2] :some-set/items [:enum/a :enum/c]}]
When I use :db/unique :db.unique/identity in a schema – 1st set is created, and the 2nd one overwrites it. When I use :db/unique :db.unique/value in a schema – I get "unique conflict" error:
:db.error/unique-conflict Unique conflict: :some-set/items, value: 17592186045438 already held by: 17592186045482 asserted for: 17592186045484
which basically says:
you cannot add :enum/a to a new :some-set/items, because :enum/a is already used in existing :some-set/items
Can I have a collection uniqueness constraint, not an item in collection one?


The actual thing I am trying to achieve – is to have "nested :cardinality/many"

:some/things [:enum/a :enum/b [:enum/a :enum/c] :enum/d]


And after few exceptions here and there this is what I came up with:

:some/things [:enum/a :enum/b {:some-set/items [:enum/a :enum/c]} :enum/d]
which works with either of these used in schema:
:db/unique :db.unique/value
:db/unique :db.unique/identity
but does not work without :db/unique set (actually it makes me either do a lot of look ups, or to create a copy of :some-set/items each time I use it to create new :some/things).