Programming with Data and EDN

Datomic is designed to be directly programmable using data. That means your application's code can use ordinary data structures to communicate with Datomic. Extensible Data Notation (EDN) is a way of representing these data structures as text. Example transactions, queries, query results, and sample data throughout this Developer Guide are presented in EDN. You can also construct the necessary data structures programmatically using any of the languages supported by Datomic.

This section explains how to read EDN notation and how to use data structures to program with Datomic. Even if you don't use EDN in your application's code, you'll want to be able to read EDN so that you can understand the examples in this Developer Guide.

Datomic Data Types

The sections below summarize the data types used by Datomic, and explain the EDN notation used to represent each type.

Following EDN convention, the examples in this Developer Guide use whitespace instead of commas to separate elements in collections. You may use commas to separate elements in collections if you wish; they will be ignored. Unless commas appear within a string, EDN treats them as whitespace.

For more detailed information, refer to the EDN specification.

Scalar Data Types for Numbers

Datomic uses the following data types to store numbers:

  • long - A fixed, signed integer in Two's complement binary representation. Has the same semantics as a Java long.
  • bigint - An arbitrary precision signed integer. Same as java.math.BigInteger on Java platforms.
  • double - A double-precision 64-bit IEEE 754 floating point number. Corresponds to a Java double.
  • float - A single-precision 32-bit IEEE 754 floating point number. Corresponds to a Java float.
  • bigdec - A floating point number with arbitrary and exact precision. Corresponds to java.math.BigDecimel.
Data TypePrecisionEDN NotationExample
long64-bit (signed integer)the digits 0-9, optional plus sign (+) or a minus sign (-) prefix42, +42, -42, 0
bigintarbitrary (signed integer)same as long with a mandatory N suffix42N, \+42N, -42N, 0N
double64-bit, doublethe digits 0-9 with a decimel point (.), optional plus sign (+) or a minus sign (-) prefix3.14, -3.14
float32-bit, singlesame as double3.13, -3.14
bigdecarbitrary and exactsame as double with a mandatory M suffix3.14M. -3.14M

Other Scalar Data Types

Datomic uses the following non-numeric scalar data types:

  • string - a string.
  • character - a single character.
  • boolean - a boolean.
  • instant - An instant in time (not a date).
  • uuid - A universally unique identifier. Corresponds to java.util.UUID.
  • symbol - Symbols are used to represent identifiers, similar to programming language keywords and variable names. Symbols may include an optional namespace in the form namespace/name.
  • keyword - Keywords are identifiers that typically designate themselves, similar to programming language enumerations. Keywords follow the rules of symbols, except they must begin with a colon (:). May include an optional namespace in the form :namespace/name.

Having dedicated non-string types for symbols and keywords makes EDN especially suitable for DSLs while retaining its all-data nature, and that is leveraged by Datomic for query and transaction syntax.

Data TypeEDN NotationExample
stringenclosed in double quotes ("")"this is a string"
characterpreceded by a backslash (\)\f, \tab, \return, \u001B
booleantrue, falsetrue, false
instant#inst followed by a string in RFC-3339 format#inst "1985-04-12T23:20:50.52Z"
UUID#uuid followed by a string in canonical UUID format#uuid "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
symbolBegins with a non-numeric character other than a colon (:) or a hash sign (#). See EDN specification for symbol chars?c, my-query-rules
keywordBegins with a colon (:). See EDN specification for keyword chars.:find, :where, :db/id, :db/doc, :namespace/foo

Collection Data Types

Datomic uses the following data types for multi-valued collections:

  • list - A list is a sequence of values. Lists are represented by zero or more elements enclosed in parentheses (). Lists may contain heterogeneous elements and scalar or nested values. The use of lists instead of vectors in Datomic syntax is optional, and is often done just to distinguish different constructs.
  • vector - A vector is a sequence of values. Vectors are represented by zero or more elements enclosed in square brackets []. Vectors may contain heterogeneous elements, and simple or nested values.
  • map - A map is a collection of associations between keys and values. Maps are represented by a set of zero or more key/value pairs, entirely enclosed in curly braces {}. Keys and values can be elements of any type. Maps may contain heterogeneous elements, and simple or nested values.
Datomic Data TypeEDN NotationExample in EDN
listenclosed in parentheses ()(1 2 3), (a b 42)
vectorenclosed in square brackets [][1 2 3], [a b 42]
mapenclosed in curly braces {}{:a 100 :b 90}, {:a 1, "foo" :bar, [1 2 3] four}

Query EDN Example

Below is an example of a query shown in EDN. This query finds all entities with a :community/name attribute whose value is "belltown".

[:find ?c :where [?c :community/name "belltown"]]

In the example above:

  • :find and :where are a symbols denoting programmatic clauses in the query
  • ?c is a symbol denoting a logic variable
  • :community/name is a namespaced keyword, used as a constant in the query, and denoting the ident <att-ref-ident> of a particular schema attribute
  • "belltown" is a string, used as a constant in the query, and denoting the desired value of the :community/name attribute
  • the entire query is a vector containing a nested vector

See the query reference for more information about query syntax.

Transaction EDN Example

Below is an example of a transaction written in EDN notation. This transaction creates a new entity with two attributes: :person/name and :person/email.

[{:person/name "Anna" :person/email "anna@example.com"}]

In the transaction above:

  • :person/name and :person/email are namespaced keywords denoting the idents <att-ref-ident> of attributes the new entity will possess
  • "Anna" is a string denoting the the value of the :person/name attribute
  • "anna@example.com" is string denoting the value of the :person/email attribute
  • the entire transaction is a vector containing a nested map

See transaction structure for more information about how transactions are structured.