Update data


An “update” is a two-step process in Datomic:

  1. Retract old fact
  2. Assert new fact

Datomic doesn’t overwrite data. “Retract” is a statement that says “this data is no longer current” which means that it won’t turn up when you query for it as of now. If you query for it as of before you will see it!

Being able to see how data develops over time is a brillant core feature of Datomic. We don’t need to administrate cumbersome historial changes manually. It’s all built in to Datomic.

Cardinality one

We need an entity id to update data so we get it first with the special generic Molecule attribute e (for entity):

val fredId = Person.e.name_("Fred").get.head


Now we can update the entity Fred’s age by applying the new value 39 to the age attribute:


Molecule uses the fredId to

  1. find the current age attribute value (38) and retract that value
  2. assert the new age attribute value 39


We can retract (“delete”) an attribute value by applying no value


This will retract the age value 39 of the Fred entity.


A cardinality many attribute like hobbies holds a Set of values:

Person(fredId).hobbies.get.head === Set("golf", "cars")

Only unique values

Since cardinality many attributes hold Sets, Molecule rejects duplicate values in all cardinality-many operations shown below.

Duplicate variables or primitive values will throw a compile-time error. Duplicate values that can only be discovered at runtime will throw an IllegalArgumentException at runtime.

Operations on card-many attrs

All operations generally accepts varargs or Iterables of the type of the attribute. So even if the attribute holds a Set of values we can also supply Seq, List or any Iterable of values.


// Add vararg values
Person(fredId).hobbies.add("walks", "jogging").update
Person(fredId).hobbies.get.head === Set("golf", "cars", "walks", "jogging")

// Add Set/Seq/Iterable of values
Person(fredId).hobbies.add(Set("skating", "biking")).update
Person(fredId).hobbies.get.head === Set("golf", "cars", "walks", "jogging", "skating", "biking")


Since Cardinality-many attributes have multiple values we need to specify which of those values we want to replace:

// Cardinality-many attribute value updated
Person(fredId).hobbies.replace("skating" -> "surfing").update
Person(fredId).hobbies.get.head === Set("golf", "cars", "walks", "jogging", "surfing", "biking")

Here we tell that the “skating” value should now be “surfing”. The old value is retracted and the new value asserted so that we can go back in time and see what the values were before our update.

Update several values in one go

  "golf" -> "badminton",
  "cars" -> "trains").update
Person(fredId).hobbies.get.head === Set("badminton", "trains", "walks", "jogging", "surfing", "biking")


We can remove one or more values from the set of values

Person(fredId).hobbies.get.head === Set("trains", "walks", "jogging", "surfing", "biking")

Person(fredId).hobbies.remove(List("walks", "surfing")).update
Person(fredId).hobbies.get.head === Set("trains", "jogging", "biking")

The retracted facts can still be tracked in the history of the database.


As with cardinality one attributes we can apply completely new values to an attribute. All old values are retracted. It’s like an “overwrite all” operation except that we can see the retracted old values in the history of the database.

Person(fredId).hobbies.get.head === Set("meditation")


Applying nothing (empty parenthesises) retracts all values of an attribute

Person(fredId).hobbies.get === Nil


Delete / retract…