Skip to content

Latest commit

 

History

History
117 lines (87 loc) · 3.67 KB

6-13_transact-retract-data.asciidoc

File metadata and controls

117 lines (87 loc) · 3.67 KB

Removing Data from a Datomic Database

by Robert Stuttaford

Problem

You need to remove data from your Datomic database.

Solution

To remove a value for an attribute, you should use the :db/retract operation in transactions.

To follow along with this recipe, first complete the recipes for [sec_datomic_connect_to_datomic], and [sec_datomic_schema].

To start things off, add a user, Barney Rubble, and verify that he has an email address:

(require '[datomic.api :as d])

(def new-id (d/tempid :db.part/user))

(def tx-result @(d/transact conn
                            [{:db/id new-id
                              :user/name "Barney Rubble"
                              :user/email "barney@rubble.me"}]))

(def after-tx-db (:db-after tx-result))

(def barney-id (d/resolve-tempid after-tx-db
                                 (:tempids tx-result)
                                 new-id))

barney-id
;; -> 17592186045429

(d/q '[:find ?email :in $ ?entity-id :where
       [?entity-id :user/email ?email]]
     after-tx-db
     barney-id)
;; -> #{["barney@rubble.me"]}

To retract Barney’s email, transact a transaction with the :db/retract operation:

(def retract-tx-result @(d/transact conn [[:db/retract barney-id
                                           :user/email "barney@rubble.me"]]))

(def after-retract-db (:db-after retract-tx-result))

(d/q '[:find ?email :in $ ?entity-id :where
       [?entity-id :user/email ?email]]
     after-retract-db
     barney-id)
;; -> #{}

To retract entire entities, use the :db.fn/retractEntity built-in transactor function:

(def retract-entity-tx-result
  @(d/transact conn [[:db.fn/retractEntity barney-id]]))

(def after-retract-entity-db (:db-after retract-entity-tx-result))

(d/q '[:find ?entity-id :in $ ?name :where
       [?entity-id :user/name ?name]]
     after-retract-entity-db
     "Barney Rubble")
;; -> #{}

Discussion

When using :db/retract, you provide the value to retract so that in the case of cardinality-many attributes, it’s clear which value to retract from the set of values for that attribute. Regardless of the cardinality, if you provide a value that isn’t in storage, nothing will be retracted. This means that you have to know what value you want to retract; you can’t simply retract everything for an attribute by only providing the entity ID and the attribute.

If you retract values for an attribute that does not use :db/noHistory, you will be able to query past database values to find past values for the attribute.

If you retract values for an attribute that uses :db/noHistory, that data will be permanently deleted.

When using :db.fn/retractEntity, all attribute values for all the attributes on that entity will be retracted, as will all :db/ref attributes that have the entity as a value. Any component entities of the entity being retracted will themselves be recursively retracted.

You’ll find that the actual entity ID itself is not retracted, but that it will have no attributes associated with it. This is because once an entity is created, it cannot be retracted. Removing all the attributes and references to the entity has the same effect as if it had been permanently removed, though!

If you need to permanently remove data due to legal concerns or because the data in question falls outside of your domain-specified retention period, use excision to remove the data permanently.

See Also