<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Datomic by example</title>
  <link href="https://github.com/borkdude/quickblog/atom.xml" rel="self"/>
  <link href="https://github.com/borkdude/quickblog"/>
  <updated>2025-08-06T14:04:22+00:00</updated>
  <id>https://github.com/borkdude/quickblog</id>
  <author>
    <name>Quick Blogger</name>
  </author>
  <entry>
    <id>https://github.com/borkdude/quickblog/todo-list-part-1.html</id>
    <link href="https://github.com/borkdude/quickblog/todo-list-part-1.html"/>
    <title>Building a TODO List App with Datomic Pro - [Part 1]</title>
    <updated>2025-04-30T23:59:59+00:00</updated>
    <content type="html"><![CDATA[<p>Are you looking for a way to get started learning Datomic, or are you picking Datomic up again after some time away from it? If so, this tutorial is for you. By building a straightforward TODO list app with Clojure and Datomic, we will identify the mental model of Datomic and demonstrate how to use its theoretical insights in a practical context. Your journey through the tutorial will equip you with the skills to continue exploring Datomic on your own. You will learn key characteristics of what makes Datomic special:</p><ul><li>Information <a href='https://docs.datomic.com/whatis/data-model.html#indelible'>accumulates over time</a>, and change is represented by accumulating the new, not by modifying or removing the old.</li><li>Powerful Declarative Query, <a href='https://docs.datomic.com/query/query.html'>Datalog</a> joins and rules provide SQL-level power, but with an easier pattern-based syntax.</li><li>Flexible <a href='https://docs.datomic.com/schema/schema.html'>schema</a>, one that can change with the changing reality of your business. <a href='https://docs.datomic.com/schema/schema-change.html'>Modify it over time</a>.</li><li>History of changes built-in, how and when changes where made. We'll use this property to list the changes of the statuses over time.</li><li>Database as a value, to execute queries a database input is expected, this input can be a database pointing at different points in time. This enables queries to any point in time out of the box.</li></ul><!-- end-of-preview --><p>As we go along, we will primarily reference <a href='https://docs.datomic.com/datomic-overview.html'>docs.datomic.com</a> and list other resources for further reading and learning and the end of each part of the tutorial.</p><p><img src="assets/full-app.gif" alt="Datomic todo-app" /></p><h2 id="who&#95;is&#95;this&#95;tutorial&#95;for?">Who is this Tutorial For?</h2><p>This tutorial is designed for Clojure and Datomic beginners or someone picking up Datomic again.  If you are totally new to Clojure, you should check out <a href='https://clojure.org/guides/getting_started'>Clojure Getting Started</a> and then come back here. </p><p>This guide aims to provide you with the skills and knowledge to get Datomic’s mental model and gain confidence to continue explore Datomic by yourself.</p><p><strong>Objectives of the Tutorial</strong></p><p>By the end of this tutorial, you will:</p><ol><li><strong>Installation</strong>: Download Datomic, run a transactor and restore a backed up database.</li><li><strong>Create a basic Clojure project and connect to a running Datomic</strong>: By the end of the tutorial you’ll have a simple Clojure project with Datomic running.</li><li><strong>How Datomic models data</strong>: Through the tutorial we’ll start from explaining the concept of datom and how it’s a crucial thing for Datomic.</li><li><strong>How run Datomic queries</strong>: Explore some of the api’s to execute queries and the basics of the Datalog engine.</li><li><strong>Universal Schema in Datomic:</strong> How Datomic treats data as first class and how to add new schemas to an existing database.</li><li><strong>Transact data to Datomic:</strong> Transact new data to the database.</li><li><strong>Build a toy app:</strong>  Build a simple application with some requirements using Datomic.</li><li><strong>Time in Datomic:</strong> Datomic is an evolving database, new facts occur as time goes on but that doesn’t mean that older facts no longer exist. By the end of the tutorial you’ll have more clear understanding on how Datomic models time and how to leverage it to make queries in different moments of the database life.</li></ol><p>This structured approach ensures you gain both theoretical and practical insights, making it easier to gain confidence to continue explore Datomic.</p><h2 id="technology&#95;requirements">Technology Requirements</h2><ul><li><a href='https://clojure.org/guides/install_clojure#java'>Java</a></li><li><a href='https://clojure.org/guides/install_clojure'>Clojure</a></li><li>Browser</li></ul><p>In a new terminal, verify that the requirements are installed properly by running the following commands.</p><pre><code class="lang-shell">clojure --version
</code></pre><pre><code class="lang-shell">;; Output
Clojure CLI version 1.12.0.1479 ;; the version might be different in your machine.
</code></pre><p>It's recommended to install the latest stable version of Clojure.</p><pre><code class="lang-shell">java --version
</code></pre><pre><code class="lang-shell">;; Output
java 21.0.4 2024-07-16 LTS
</code></pre><p>It should work with Java 11+.</p><h2 id="what&#95;is&#95;a&#95;datomic&#95;database?">What is a Datomic Database?</h2><p>A Datomic database is a single universal relation of facts called datoms. Datoms can be either assertions indicating that something is known to be true at a point in time or retractions indicating that something is no longer known to be true. Datoms are atomic and immutable. Datomic transactions atomically add a set of datoms to a database, they never update or remove anything. A fact is something that occurred, time is part of the definition of that fact, thus we can query the database with the time at hand for "as-of" points in time. "At this moment of time my database is this value", the queries I make will return the same result until I pass a different value of the database. In contrast things in a server oriented database could have changed between query one and query two, because we are asking questions in terms of a place/time, we are able to leverage the database as a value for Datomic operations.</p><p>Datomic is a database that is fundamentally different, as we go over the tutorial we'll exemplify what is stated above. The docs website contains a very complete explanation on the architecture of Datomic, the tutorial will only explain some concepts briefly and you're encouraged to complement the lessons you are learning here with reading the documentation. </p><h3 id="quick&#95;intro&#95;to&#95;datomic's&#95;data&#95;modelling">Quick intro to Datomic's data modelling</h3><p>Data is modeled as entities, attributes, values, transaction, and op information all in a single tuple <code>&#91;entity, attribute, value, transaction op&#93;</code>. In Datomic this is called a “datom” (<em>An atomic fact in a database</em>).</p><p>We’ll refer to this tuple as <code>&#91;e a v t op&#93;</code>.</p><p>Given the following map</p><pre><code class="lang-clojure">&#40;def db-example
  &#91;{:list/name &quot;life&quot;
    :list/items &#91;{:item/text &quot;travel&quot;
                  :item/status :item.status/:todo}
                 {:item/text &quot;buy coffee&quot;
                  :item/status :item.status/:todo}&#93;}
   {:list/name &quot;learn&quot;
    :list/items &#91;{:item/text &quot;clojure&quot;
                  :item/status :item.status/:todo}
                 {:item/text &quot;datomic&quot;
                  :item/status :item.status/:todo}&#93;}&#93;&#41;
</code></pre><p>we can represent it in a Datomic database like this;</p><p><img src="assets/datoms.png" alt="datoms table example" /></p><p><i>values in the image are simplified</i></p><p>Datomic is a single table that accumulates datoms, the "e" position is the entity identifier, all of the datoms that have the 45418 in the "e" relate to the same entity, we call this number <strong>eid</strong>. The "a" is self explanatory, refers to the attribute we are talking about. The "v" has the value of such attribute. The "t" is the transaction, it tells when the datom was persited and it's possible that many datoms share the same "t", in the example we se the number 34321 in 6 places, that tells us that those 6 datoms were transacted at the same moment. Lastly, "op" is a boolean that tells if that datom remains true, we will talk more  about this when introducing retraction, to briefly explain it, when the "op" is false means that the "v" is no longer a reality.</p><blockquote><p> Datomic makes first-class relationships </p></blockquote><p>The arrows ilustrate that number 45422 points to the "travel" datom and that 45427 points to the "datomic" datom. Datomic provides these references for users to make the relationships.</p><p>Attribute "a" can be defined as cardinality <strong>one</strong> or cardinality <strong>many</strong>. "One" means only one datom for a given eid can be true or absence of value. "Many" means that multiple datoms for a given eid can hold the true "op", <code>:list/items</code> is an example of that, we see <code>&#91;45418 :list/items 45422 344317 true&#93;</code> and <code>&#91;45418 :list/items 45424 344319 true&#93;</code>. In these <code>:list/items</code> datoms we have number 45422 and number 45424 in the "v" position, both are part of the "life" list.</p><h3 id="what&#95;about&#95;the&#95;“t”?">What about the “t”?</h3><p>When data is transacted to the database Datomic will create a t datom that will contain the time information about when those “datoms” were added. Datomic will place it in the “t” spot of [e a v <strong>t</strong>]</p><h2 id="building&#95;the&#95;app">Building the App</h2><p>We want to build an app that will do everything we typically expect of a TODO app (create list items, mark items completed, delete items), plus a couple of powerful features that Datomic makes it trivial to enable them. For example, have you ever wanted add some time filters so that you could ask your app, "How was my life yesterday?" and display the evolution of the statuses of an item, a history log of changes. In <em>Part 1</em>, we'll focus on the foundation that will allow us to add more features as we go.</p><h3 id="parts">Parts</h3><ol><li>Install Datomic and explore it using the REPL</li><li>Create an HTTP server and render a simple UI</li><li>Create, Read, Update, Delete - Lists and Items</li><li>Add filters, time based, by status and display the history of status transitions</li><li>Deploy application to the web</li></ol><h3 id="technologies">Technologies</h3><p>We'll keep dependencies small.</p><ul><li><a href='https://clojure.org/'>Clojure</a></li><li><a href='https://www.datomic.com/'>Datomic</a></li><li><a href='http://pedestal.io/pedestal/0.7/index.html'>Pedestal</a> for HTTP server</li><li><a href='https://github.com/weavejester/hiccup'>Hiccup</a> for HTML and CSS. No need for JavaScript!</li></ul><h4 id="project&#95;structure">Project structure</h4><p>Choose a place in your file system to create a new project, in this tutorial we’ll use the path when a new terminal is open.  We’ll follow this structure.</p><pre><code>.
├── deps.edn
└── src
    └── todo&#95;db.clj
</code></pre><h4 id="how&#95;to&#95;follow&#95;the&#95;code&#95;blocks?">How to follow the code blocks?</h4><p>The tutorial focuses in explaining key concepts about Datomic and exemplifying them with code examples that run in the Clojure REPL. When there is a code block with <code>;; REPL</code> comment at the top it means that the code should run the the REPL. If it doesn't have that comment it's just an example to assist an explanation. </p><h4 id="code&#95;examples&#95;repository">Code examples repository</h4><p>The code can be found in <a href='https://github.com/Datomic/datomic-tutorials/tree/main/todo-app/part-1/todo-app'>datomic-tutorials</a></p><h3 id="installation">Installation</h3><p>Open a new terminal and download <a href='https://docs.datomic.com/releases-pro.html'>datomic-pro</a></p><pre><code class="lang-shell">curl https://datomic-pro-downloads.s3.amazonaws.com/1.0.7277/datomic-pro-1.0.7277.zip
</code></pre><p>unzip the file</p><pre><code class="lang-shell">unzip datomic-pro-1.0.7277.zip -d .
</code></pre><h4 id="run&#95;transactor&#95;with&#95;default&#95;properties">Run transactor with default properties</h4><p>The <strong>transactor</strong> is a process with the ability to commit transactions for a given database. </p><p>In the same terminal, run the following command to start the transactor:</p><pre><code class="lang-shell">datomic-pro-1.0.7277/bin/transactor config/samples/dev-transactor-template.properties
</code></pre><pre><code class="lang-shell">;; Output
Launching with Java options -server -Xms1g -Xmx1g -XX:+UseG1GC -XX:MaxGCPauseMillis=50
System started
</code></pre><p>Now that we have a running transactor we can start working on the code.</p><h2 id="repl&#95;explorations">REPL Explorations</h2><p>Let's do some REPL exploration and get some practice with Datomic essentials:</p><ol><li>Setup a connection to Datomic using the Clojure library</li><li>Define and install schema</li><li>Transact novel data</li><li>Examples using query</li></ol><p>Add the following to <code>deps.edn</code>.</p><pre><code class="lang-clojure">{:deps {org.clojure/clojure {:mvn/version &quot;1.12.0&quot;}
        com.datomic/peer {:mvn/version &quot;1.0.7277&quot;}
        io.pedestal/pedestal.jetty {:mvn/version &quot;0.7.1&quot;}
        org.slf4j/slf4j-simple {:mvn/version &quot;2.0.10&quot;}
        hiccup/hiccup {:mvn/version &quot;2.0.0-RC3&quot;}}}
</code></pre><p>For now, we'll focus in the <code>com.datomic/peer</code> library. The rest will come handy when building the browser UI.</p><h3 id="define&#95;and&#95;transact&#95;schemas">Define and transact schemas</h3><p>Schemas follow the same rules as transacting any other data, they are also datoms.</p><table><thead><tr><th style='text-align:left'><strong>Name</strong></th><th style='text-align:left'><strong>Purpose</strong></th><th style='text-align:left'><strong>Required?</strong></th></tr></thead><tbody><tr><td style='text-align:left'><code>:db/ident</code></td><td style='text-align:left'>specifies a unique programmatic name for an entity (normally a schema entity)</td><td style='text-align:left'><a href='https://docs.datomic.com/schema/schema-reference.html#db-ident'>Required</a> for schema entities</td></tr><tr><td style='text-align:left'><code>:db/cardinality</code></td><td style='text-align:left'>specifies whether an attribute associates a single value or a set of values</td><td style='text-align:left'><a href='https://docs.datomic.com/schema/schema-reference.html#db-cardinality'>Required</a></td></tr><tr><td style='text-align:left'><code>:db/valueType</code></td><td style='text-align:left'>specifies the type of value that can be associated with an attribute</td><td style='text-align:left'><a href='https://docs.datomic.com/schema/schema-reference.html#db-valuetype'>Required</a></td></tr><tr><td style='text-align:left'><code>:db/unique</code></td><td style='text-align:left'>specifies a uniqueness constraint for the values of an attribute</td><td style='text-align:left'><a href='https://docs.datomic.com/schema/schema-reference.html#db-unique'>Optional</a></td></tr></tbody></table><p><em>To know more, take a look at the full list of attributes available for schemas in the <a href='https://docs.datomic.com/schema/schema-reference.html#defining-schema'>official docs.</a></em></p><p>Let's define the uses cases and properties of the application and then create a schema that matches the requirements.</p><ol><li>Group todo items to a list and be able to have multiple lists</li><li>Lists and items can be created and deleted</li><li>Items should be ordered (e.g last created at)</li><li>Todo items need to have an status (e.g done)</li><li>Item status can be updated</li></ol><p>The relationship can be, "lists have many items", in other words the cardinality of items in terms of list is "many".</p><p><img src="assets/todo-diagram.png" alt="" /></p><h4 id="a&#95;word&#95;on&#95;refs">A word on refs</h4><p>When <code>:db.type/ref</code> is defined, the reference can be to any other <a href='https://docs.datomic.com/glossary.html#entity'>entity</a> in the database, Datomic doesn't restrict to reference only to a specific entity, that's a bussiness domain defined in the application.</p><pre><code class="lang-clojure">;; REPL
&#40;def schema
  &#91;{:db/ident       :list/name
    :db/valueType   :db.type/string
    :db/cardinality :db.cardinality/one
    :db/unique      :db.unique/identity
    :db/doc         &quot;List name&quot;}
   {:db/ident       :list/items
    :db/valueType   :db.type/ref;; reference
    :db/cardinality :db.cardinality/many
    :db/doc         &quot;List items reference&quot;}
   {:db/ident       :item/status
    :db/valueType   :db.type/keyword
    :db/cardinality :db.cardinality/one
    :db/doc         &quot;Item Status&quot;}
   {:db/ident       :item/text
    :db/valueType   :db.type/string
    :db/cardinality :db.cardinality/one
    :db/doc         &quot;Item text&quot;}&#93;&#41;
</code></pre><p><em>Learn more about defining schema in Datomic <a href='https://docs.datomic.com/schema/schema-reference.html#defining-schema'>here</a></em></p><p><strong>To transact a schema you need to:</strong></p><ol><li>Define the <code>db-uri</code><pre><code class="lang-clojure">;; REPL
&#40;def db-uri &quot;datomic:dev://localhost:4334/todo&quot;&#41;
</code></pre></li><li>Create the database<pre><code class="lang-clojure">;; REPL
&#40;d/create-database db-uri&#41;
</code></pre></li><li>Establish a connection<pre><code class="lang-clojure">;; REPL
&#40;def conn &#40;d/connect db-uri&#41;&#41;
</code></pre></li><li>Transact the schema with <a href='https://docs.datomic.com/clojure/index.html#datomic.api/transact'>d/transact</a>.<pre><code class="lang-clojure">;; REPL
@&#40;d/transact conn schema&#41;
</code></pre></li></ol><p><em>d/transact returns a promise, we use @ to <a href='https://clojuredocs.org/clojure.core/deref'>deref</a> it</em></p><p>With the schema transacted, we are able to store some lists and items.</p><h3 id="how&#95;does&#95;datomic&#95;transacts&#95;data?">How does Datomic transacts data?</h3><p>Datomic represents transaction data as <a href='https://docs.datomic.com/reference/data-structure-literals.html'>data structures</a>. This is a significant difference from SQL databases, where requests are submitted as strings. Using data instead of strings makes it easier to build requests programatically. Remember that a datom is [e a v t], when transacting data we need to provide the first 3 and Datomic will create the “t”.  Datomic has two forms of structures, list and maps.</p><p>This is the structure of a list form <code>&#91;op entity-id attribute value&#93;</code></p><pre><code class="lang-clojure">&#40;d/transact conn &#91;&#91;:db/add &quot;42&quot; :list/name &quot;life&quot;&#93;&#93;&#41;
</code></pre><p>The <a href='https://docs.datomic.com/transactions/transaction-data-reference.html#map-forms'>map form</a> is a convenient shorthand when making several assertions about the same entity. The map has an optional <em>:db/id</em> key identifying the entity, plus any number of attribute/value pairs. When creating a new entity we can exclude the :db/id and Datomic will generate a new one.</p><pre><code class="lang-clojure">&#40;d/transact conn &#91;{:list/name &quot;life&quot;}&#93;&#41;
</code></pre><h4 id="transact&#95;a&#95;new&#95;list">Transact a new list</h4><p>Now, transact a new list with name "life"<pre><code class="lang-clojure">;; REPL
@&#40;d/transact conn &#91;{:list/name &quot;life&quot;}&#93;&#41;
</code></pre></p><pre><code class="lang-clojure">;; Result
{:db-before datomic.db.Db@c5277e1, 
 :db-after datomic.db.Db@b415356f, 
 :tx-data
  &#91;#datom&#91;13194139534316 50 #inst &quot;2025-03-25T19:54:47.185-00:00&quot; 13194139534316 true&#93;
   #datom&#91;17592186045421 72 &quot;life&quot; 13194139534316 true&#93;&#93;,
 :tempids {-9223300668110598127 17592186045421}}
</code></pre><p>The result of a transaction contains;</p><ul><li><code>:db-before</code> = database value before the transaction</li><li><code>:db-after</code> = database value after the transaction</li><li><code>:tx-data</code> = datoms produced by the transaction</li><li><code>:tempids</code> = tempid resolution, from the string we chose to the actual value in the database.</li></ul><blockquote><p> The tx-report enables straight forward comparisons before and after data is transacted. We can use the <code>:db-before</code> to make queries to the past. Remember, with Datomic the db's are values and we can pass those values around, queries will return the same result if it's executed to the same db value. Db values don't mutate, you can take your time and process them, there is no need to lock the world. </p></blockquote><p>To showcase a quick example of that, create another list called <code>learn</code> —but this time we are going to save the result in a var and then access to the result values.</p><pre><code class="lang-clojure">;; REPL
&#40;def result @&#40;d/transact conn &#91;{:list/name &quot;learn&quot;}&#93;&#41;&#41; ;; new list
&#40;def my-list-q
  '&#91;:find ?list
    :in $
    :where &#91;?list :list/name &quot;learn&quot;&#93;&#93;&#41;

&#40;d/q my-list-q &#40;:db-after result&#41;&#41; ;; IMPORTANT line
</code></pre><pre><code class="lang-clojure">;; Result
#{&#91;17592186045423&#93;} ;; the result number might be different for you, it's okay.
</code></pre><pre><code class="lang-clojure">;; REPL
&#40;d/q my-list-q &#40;:db-before result&#41;&#41;
</code></pre><pre><code class="lang-clojure">;; Result
#{}
</code></pre><p>With <code>&#40;def result @&#40;d/transact conn &#91;&#40;new-list &quot;learn&quot;&#41;&#93;&#41;</code>, you can run the same query with <code>&#40;:db-after result&#41;</code> or <code>&#40;:db-before result&#41;</code>, the first returns the <i>eid</i> of the list in the database, the second is empty because at that point in time the list didn't exist.</p><blockquote><p> This is a simple example of the <strong>out-of-the-box</strong> support for making queries at different moments of time by leveraging a database as a value rather than a connection. </p></blockquote><p><em>learn more about <a href='https://docs.datomic.com/whatis/data-model.html#time-model'>Datomic time model</a></em></p><h4 id="transact&#95;new&#95;items">Transact new items</h4><p>With a list transacted, let's start adding some items. We'll follow the same pattern: create a function <code>new-item</code> that receives a <em>list-name</em> and the "todo" string. We are also including the <a href='https://docs.datomic.com/glossary.html#database'>db</a> since we want to get the <i>eid</i> of the list to make the correct relationship.</p><pre><code class="lang-clojure">;; REPL
&#40;defn new-item &#91;db list-name item-text&#93;
  {:db/id &#40;d/entid db &#91;:list/name list-name&#93;&#41;
   :list/items &#91;{:db/id &#40;d/tempid :db.part/user&#41;
                 :item/text item-text
                 :item/status :item.status/todo}&#93;}&#41;
</code></pre><p>To get the <i>eid</i> of an entity we can use <code>d/entid</code> function that receives a db and a <a href='https://docs.datomic.com/schema/identity.html#lookup-refs'>lookup ref</a>. We pass the <i>eid</i> to tell Datomic that we want to do an assertion over an existing entity. Notice that for the <code>:db/id</code> inside <code>:list/items</code> we make use of <a href='https://docs.datomic.com/transactions/transaction-data-reference.html#tempids'>tempids</a> by calling the function <a href='https://docs.datomic.com/clojure/index.html#datomic.api/tempid'>d/tempid</a>. This is because we are creating a new nested entity. Datomic requires that a <a href='https://docs.datomic.com/transactions/transaction-data-reference.html#nested-maps-in-transactions'>nested map</a> either be referenced by a component attribute or include a unique attribute. This constraint prevents the accidental creation of easily-orphaned entities that have no unique identity or relation to other entities.</p><pre><code class="lang-clojure">;; REPL
@&#40;d/transact conn &#91;&#40;new-item &#40;d/db conn&#41; &quot;life&quot; &quot;travel&quot;&#41;&#93;&#41;
</code></pre><p>let's populate the list <code>life</code> with more data and run some exploration queries.</p><pre><code class="lang-clojure">;; REPL
&#40;-&gt;&gt; &#91;&quot;play drums&quot; &quot;scuba dive&quot; &quot;buy coffee&quot;&#93;
     &#40;map &#40;partial new-item &#40;d/db conn&#41; &quot;life&quot;&#41;&#41;
     &#40;d/transact conn&#41;&#41;
</code></pre><p>Add items to the <code>learn</code> list.</p><pre><code class="lang-clojure">;; REPL
&#40;-&gt;&gt; &#91;&quot;clojure&quot; &quot;datomic&quot; &quot;sailing&quot; &quot;cook rissotto&quot;&#93;
     &#40;map &#40;partial new-item &#40;d/db conn&#41; &quot;learn&quot;&#41;&#41;
     &#40;d/transact conn&#41;&#41;
</code></pre><h4 id="retract&#95;items">Retract items</h4><p>An addition indicates that a datom is true at a point in time, and a retraction indicates that a datom is not true at a point in time. When adding a retraction, it is persiting a datom with the "op" as false, that tells Datomic that the fact can be ignore for the current present, unless explicitly asking to include datoms that are false, we will cover more on this on part 4 when talking about <a href='https://docs.datomic.com/reference/filters.html'>filters</a>.</p><p>retract the "buy coffee" item from the "life" list.</p><ul><li>Get the <i>eid</i> of the "buy coffee item"</li><li>Call the <code>:db/retract</code> fn and pass the <i>eid</i></li></ul><pre><code class="lang-clojure">;; REPL
&#40;def eid &#40;ffirst
           &#40;d/q '&#91;:find ?item
                  :in $
                  :where &#91;?item :item/text &quot;buy coffee&quot;&#93;&#93;
                &#40;d/db conn&#41;&#41;&#41;
@&#40;d/transact conn &#91;&#91;:db/retract eid :item/text&#93;&#93;&#41;
</code></pre><p><img src="assets/retract-item.png" alt="datoms table example" /></p><p>to ilustrate the accumulation of datoms in the table we can see that <code>&#91;45424 :item/text &quot;buy coffee&quot; 34322 false&#93;</code> is added. It is placed in that position because Datomic maintains four covering <a href='https://docs.datomic.com/indexes/indexes.html'>indexes</a> that contain ordered sets of datoms. The picture shows EAVT, which is sorted first by "E" then "A" then "V" and finaly "T", that's why we see the descending ordering in the A column.</p><h3 id="how&#95;does&#95;datomic&#95;queries&#95;data?">How does Datomic queries data?</h3><p>Datomic uses <a href='https://docs.datomic.com/whatis/supported-ops.html#datalog'>Datalog</a> as query engine. A query finds <a href='https://docs.datomic.com/glossary.html#value'>values </a>in a <a href='https://docs.datomic.com/glossary.html#database'>database </a> subject to the given constraints, and is specified as <a href='https://docs.datomic.com/glossary.html#edn'>edn</a>. Queries are modeled following the same pattern of a datom <code>&#91;e a v t&#93;</code>, if we understand this structure queries can become very powerful.</p><p>Currently, we transacted 2 lists and a few items. Let's start with some simple queries to get things going.</p><blockquote><p> The query engine runs locally in the application server, queries execute with a local db value not against a connection. You can hold the value as much time as you want and the result will always be the same. Running queries through a connection doesn't guarantee that you get the same value every time. </p></blockquote><p><strong>Get lists and their names</strong></p><pre><code class="lang-clojure">;; REPL
&#40;d/q '&#91;:find ?list-name
       :in $
       :where &#91;?list :list/name ?list-name&#93;&#93;
  &#40;d/db conn&#41;&#41;
</code></pre><pre><code class="lang-clojure">;; Result
#{&#91;&quot;life&quot;&#93; &#91;&quot;learn&quot;&#93;}
</code></pre><ul><li><code>:find</code> = specifies what you want to be returned from the query. In this case, <code>?list</code> is a logic variable that will be bound within the <code>:where</code> clause.</li><li><code>:in</code> = tells what are the inputs that the query will run against. The $ is the database and the rest are optional logic variables.</li><li><code>:where</code> = tells what datoms to retrieve.</li></ul><p><strong>Get lists + items</strong></p><pre><code class="lang-clojure">;; REPL
&#40;d/q '&#91;:find ?list-name ?items
       :in $
       :where &#91;?list :list/name ?list-name&#93;
              &#91;?list :list/items ?items&#93;&#93;
  &#40;d/db conn&#41;&#41;
</code></pre><pre><code class="lang-clojure">;; Result
#{&#91;&quot;life&quot; 17592186045422&#93; &#91;&quot;life&quot; 17592186045426&#93; &#91;&quot;life&quot; 17592186045425&#93;
  &#91;&quot;life&quot; 17592186045424&#93; &#91;&quot;learn&quot; 17592186045428&#93; &#91;&quot;learn&quot; 17592186045429&#93;
  &#91;&quot;learn&quot; 17592186045430&#93; &#91;&quot;learn&quot; 17592186045431&#93;}
</code></pre><p>A set of vectors repeating the list name? It's similar to Clojure, at first glance looks different and it's because it is a different way to interact with a database. Let's break it down, first thing we see is the repetition of the list name, e.g <code>&#91;&quot;life&quot; 17592186045425&#93;</code> and the same case for "<em>learn</em>". The schema is defined as <code>:db.cardinality/many</code> on the <code>:list/items</code> attribute, in other words we are allowing many items being referenced by <code>:list/items</code>. That makes the result make sense. It's telling us that the list "life" has many items, each one a reference.</p><p><strong>Get lists + items different version</strong></p><pre><code class="lang-clojure">;; REPL
&#40;d/q '&#91;:find ?list-name &#40;vec ?items&#41;
       :in $
       :where &#91;?list :list/name ?list-name&#93;
              &#91;?list :list/items ?items&#93;&#93;
     &#40;d/db conn&#41;&#41;
</code></pre><pre><code class="lang-clojure">;; Result
&#91;&#91;&quot;learn&quot; &#91;17592186045428 17592186045429 17592186045430 17592186045431&#93;&#93;
 &#91;&quot;life&quot; &#91;17592186045422 17592186045426 17592186045425 17592186045424&#93;&#93;&#93;
</code></pre><p>The difference is <code>&#40;vec ?items&#41;</code>, which is grouping all of the items of a list. The items are also numbers, which is because we are just pulling the reference number to the entity (<i>eid</i>). If we want to get the attributes of the Item, we need to ask for that explicitly.</p><p><strong>Get lists + items using pull</strong></p><blockquote><p> Entities <strong>do not exist on their own</strong>, entities are an association of datoms. </p></blockquote><p>In this section we will introduce the expression <a href='https://docs.datomic.com/query/query-data-reference.html#pull-expressions-example'>pull</a>. Pull is a declarative way to make hierarchical (and possibly nested) selections of information about entities. Pull applies a pattern to a collection of entities, building a map for each entity.</p><pre><code class="lang-clojure">;; REPL
&#40;d/q '&#91;:find &#40;pull ?list &#91;:list/name {:list/items &#91;:item/text&#93;}&#93;&#41;
       :in $
       :where &#91;?list :list/name ?list-name&#93;&#93;
     &#40;d/db conn&#41;&#41;
</code></pre><pre><code class="lang-clojure">;; Result
&#91;&#91;#:list{:name &quot;life&quot;
         :items &#91;#:item{:text &quot;travel&quot;}
                 #:item{:text &quot;play drums&quot;}
                 #:item{:text &quot;scuba dive&quot;}&#93;}
  &#91;#:list{:name &quot;learn&quot;
          :items &#91;#:item{:text &quot;clojure&quot;}
                  #:item{:text &quot;datomic&quot;}
                  #:item{:text &quot;sailing&quot;}
                  #:item{:text &quot;cook rissotto&quot;}&#93;}&#93;&#93;&#93;
</code></pre><h3 id="order&#95;of&#95;items">Order of items</h3><p>As a simplification, we will order items by their entity eid, which corresponds to transaction order (when only one item is added per transaction.) If different sorts are desired, you can sort the items "in post query", using normal Clojure code, or you could assert additional attributes about list items to facilitate different sorts.</p><h4 id="connecting&#95;the&#95;dots">Connecting the dots</h4><p>We have:</p><ul><li>An initial schema</li><li>A function to create new lists</li><li>A function to create new items</li><li>Some queries to fetch the state of the database</li></ul><p>With some embellishment to the code, we have this initial <a href='https://github.com/Datomic/datomic-tutorials/blob/main/todo-app/part-1/todo-app/src/todo_db.clj'>src/todo_db.clj</a> file.</p><pre><code class="lang-clojure">&#40;ns todo-db
  &#40;:require
   &#91;datomic.api :as d&#93;&#41;&#41;

&#40;def schema
  &#91;{:db/ident       :list/name
    :db/valueType   :db.type/string
    :db/cardinality :db.cardinality/one
    :db/unique      :db.unique/identity
    :db/doc         &quot;List name&quot;}
   {:db/ident       :list/items
    :db/valueType   :db.type/ref;; reference
    :db/cardinality :db.cardinality/many
    :db/doc         &quot;List items reference&quot;}
   {:db/ident       :item/status
    :db/valueType   :db.type/keyword
    :db/cardinality :db.cardinality/one
    :db/doc         &quot;Item Status&quot;}
   {:db/ident       :item/text
    :db/valueType   :db.type/string
    :db/cardinality :db.cardinality/one
    :db/doc         &quot;Item text&quot;}&#93;&#41;

&#40;def db-uri &quot;datomic:dev://localhost:4334/todo&quot;&#41;

;; INFO: Creates the database, if it does not exist returns false
&#40;d/create-database db-uri&#41; ;; it requires a running transactor

;; INFO: to delete a database use `d/delete-database`
&#40;comment &#40;d/delete-database db-uri&#41;&#41;

;; Connect to the database
&#40;def conn &#40;d/connect db-uri&#41;&#41;

&#40;comment @&#40;d/transact conn schema&#41;&#41;

&#40;defn new-list 
  &quot;receives a `list-name` and returns a new List datom.&quot;
  &#91;list-name&#93;
  {:list/name list-name}&#41;

&#40;defn new-item
  &quot;recives a `db` a `list-name` and the `item-text` and
   returns a map form of datoms to add items to a list.&quot;
  &#91;db list-name item-text&#93;
  {:db/id &#40;d/entid db &#91;:list/name list-name&#93;&#41;
   :list/items &#91;{:db/id &#40;d/tempid :db.part/user&#41;
                 :item/text item-text
                 :item/status :item.status/todo}&#93;}&#41;
</code></pre><h2 id="references">References</h2><ul><li><a href='https://docs.datomic.com/datomic-overview.html'>Datomic - docs</a></li><li><a href='https://docs.datomic.com/query/query-pull.html'>Datomic - pull</a></li><li><a href='https://docs.datomic.com/schema/schema-reference.html#defining-schema'>Datomic - defining a schema</a></li><li><a href='https://docs.datomic.com/schema/schema-reference.html#db-cardinality'>Datomic - db cardinality</a></li><li><a href='https://docs.datomic.com/glossary.html#datom'>Datomic - datom</a></li><li><a href='https://docs.datomic.com/transactions/transaction-data-reference.html#tempids'>Datomic - tempid</a></li><li><a href='https://docs.datomic.com/glossary.html#entity-id'>Datomic - entity-id</a></li><li><a href='https://docs.datomic.com/glossary.html#database'>Datomic - db</a></li><li><a href='https://docs.datomic.com/transactions/transaction-data-reference.html#map-forms'>Datomic - map forms</a></li><li><a href='https://docs.datomic.com/schema/identity.html#lookup-refs'>Datomic - lookup ref</a>.</li><li><a href='https://docs.datomic.com/whatis/supported-ops.html#datalog'>Datomic - Datalog</a></li><li><a href='https://docs.datomic.com/glossary.html'>Datomic - Glossary </a></li><li><a href='https://docs.datomic.com/glossary.html#edn'>edn</a></li><li><a href='https://clojure.org/'>Clojure</a></li><li><a href='http://pedestal.io/pedestal/0.7/index.html'>Pedestal</a> HTTP server</li><li><a href='https://github.com/weavejester/hiccup'>Hiccup</a> for HTML and CSS</li></ul>]]></content>
  </entry>
</feed>
