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.
Quickstart Video
A 70 second overview of EDN can be found at the EDN Live Tutorial.
A video is available on Youtube as well.
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; however, they will be ignored by the reader. EDN treats commas as whitespace unless they appear inside a string.
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.BigDecimal
.
Data Type | Precision | EDN Notation | Example |
---|---|---|---|
long | 64-bit (signed integer) | the digits 0-9, optional plus sign (+) or a minus sign (-) prefix | 42 , +42 , -42 , 0 |
bigint | arbitrary (signed integer) | same as long with a mandatory N suffix | 42N , +42N , -42N , 0N |
double | 64-bit, double | the digits 0-9 with a decimal point (.), optional plus sign (+) or a minus sign (-) prefix | 3.14 , -3.14 |
float | 32-bit, single | same as double | 3.13 , -3.14 |
bigdec | arbitrary and exact | same as double with a mandatory M suffix | 3.14M , -3.14M |
Other Scalar Data Types
Datomic uses the following non-numeric scalar data types (syntax indicated in table below):
- 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 Type | EDN Notation | Example |
---|---|---|
string | enclosed in double quotes ("") | "this is a string" |
character | preceded by a backslash (\) | \f , \tab , \return , \u001B |
boolean | true, false | true , 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" |
symbol | Begins with a non-numeric character other than a colon (:) or a hash sign (#). Check EDN specification for symbol chars | ?c , my-query-rules |
keyword | Begins with a colon (:). Check 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 Type | EDN Notation | Example in EDN |
---|---|---|
list | enclosed in parentheses () | (1 2 3) , (a b 42) |
vector | enclosed in square brackets [] | [1 2 3] , [a b 42] |
map | enclosed 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 the IDs
of 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 keywords 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.
Check transaction structure for more information about how transactions are structured.