In Molecule we can populate a molecule with data and save it:"Fred").likes("pizza").age(38).save

This will assert 3 facts in Datomic that all share the id of the new entity id fredId that is automatically created by Datomic:

fredId    :Person/name    "Fred"
fredId    :Person/likes   "pizza"
fredId    :Person/age     38


Type-safety is guaranteed since each attribute only accepts values of its defined type.

Asynchronous save

All transactional operators have an asynchronous equivalent. Saving data asynchronously with saveAsync uses Datomic’s asynchronous API and returns a Future with a TxReport.

Here, we map over the result of saving asynchronously:

// Map over a Future"Fred").likes("pizza").age(42) { tx => // tx report from successful save transaction
  // (synchronous get) === ("Ben", "pizza", 42)

Or we could defer the resolution of the Future

val futureSave: Future[TxReport] ="Fred").likes("pizza").age(42).saveAsync
for {
  _ <- futureSave
  result <-
} yield {
  // Data was saved
  result.head === ("Ben", "pizza", 42)

For brevity, the following examples use the synchronous save operation.

We can even save related date in the same operation"Fred").likes("pizza").age(38).Home.street("Baker St. 7").city("Boston").save

In this case, 6 facts will be asserted for the entity of Fred. A :Person/home ref attribute will resolve to the value of a new Address entity with id addrId and thereby establish the relationship from Fred to his Address:

fredId    :Person/name    "Fred"
fredId    :Person/likes   "pizza"
fredId    :Person/age     38
fredId    :Person/home    addrId
addrId    :Addr/street    "Baker St. 7"
addrId    :Addr/city      "Boston"

And we could go on with further relationships…

Cardinality many values

Cardinality many attributes like for instance hobbies hold Sets of values. But we can apply values in various ways:

// Vararg
Person.hobbies("golf", "chess").save

// Set
val set = Set("golf", "chess")

// Seq/List
val seq = Seq("golf", "chess")

Optional values

An optional value (optionalLikes) from a form submission for instance can be applied to an optional attribute (likes$):$(optionalLikes).age(anAge).save

When this molecule is saved, only 2 facts will be asserted:

fredId    :Person/name    "Fred"
fredId    :Person/age     38

This is different from SQL where we would save a NULL value in a likes column.

Molecule lets us fetch data sets with optional facts asserted for an attribute as optional values:$.age.get === List(
  ("Fred", None, 38),
  ("Pete", Some("sushi"), 17)

If we specifically want to find Persons that have no likes asserted we can say === List(
  ("Fred", 38)
  // Pete not returned since he likes something

.. or$(None).age.get === List(
  ("Fred", None, 38)
  // Pete not returned since he likes something


Create / Insert…