Search code examples
clojuredatomic

retracting :db/ident from an entity


I have a bunch of entities that are special, but they are not part of the db schema. Since these entities are special I set some :db/ident attributes to them to have easy access to them in my programs.

Lets say I call one of these accounts :base-account Now the problem is that when I use entity api to access these entities I have this problem:

;; access some entity that references one of the special entities
> (d/touch (d/entity db 12345678))
==> 
{:transaction/amount 22334455,
 :transaction/from {:db/id 0987654}, ;; normal reference to an entity
 :transaction/to :base-account} ;; this is a reference to a special account with a :db/ident attribute

This causes me problems in some of the code I have written before, because this will not give me the details of the :transaction/to account.

So to solve this problem I removed the :db/ident attributes from these entities:

> (d/transact connection [[:db/retract id-of-the-special-account
                           :db/ident :base-account]])

Which successfully removes the :db/ident from the entity:

> (:db/ident (d/entity db id-of-the-special-account))
==> nil

But for some reason (maybe a bug), the entity api call still refers to it with its old identity:

> (d/entity db :base-account) ;; should not work
==> {:db/id id-of-the-special-account}

So how can I remove the identity from these entities without having to remove them from the database altogether? Or maybe a way to fix the way the (d/entity ....) call works, in a sane way?

EDIT: I'm using datomic-pro-5544


Solution

  • From the Datomic Docs:

    Idents should be used for two purposes: to name schema entities and to implement enumerated tags. Both of these uses are demonstrated in the introductory tutorial. To support these usages, idents have two special characteristics:

    • Idents are designed to be extremely fast and always available. All idents associated with a database are stored in memory in every Datomic transactor and peer.
    • When you navigate the entity API to a reference that has an ident, the lookup will return the ident, not another entity.

    That last bullet point might be what is affecting you.

    Next paragraph:

    These characteristics also imply situations where idents should not be used:

    • Idents should not be used as unique names or ids on ordinary domain entities. Such entity names should be implemented with a domain-specific attribute that is a unique identity.
    • Idents should not be used as names for test data. (Your real data will not have such names, and you don't want test data to behave differently than the real data it simulates.)

    From this it seems like you might want to re-design the DB, rather than trying to un-do your use of :db/ident.