Datomic's database log is a recording of all transaction data in historic order, organized for efficient access by transaction. You can access the log:
- Programmatically from methods on Connection
- Via helper functions inside query
Datomic's log is stored as a shallow tree of segments, where each segment typically contains thousdands of datoms. The most recent data in the log is also maintained in memory on all transactor and peer processes.
Connection.log and Log.txRange
You can access the log via Connection.log:
datomic.Log log = conn.log();
Given a log, you can retrieve an Iterable over a range in the log with Log.txRange:
Iterable<Map> range = log.txRange(1000, 1020);
The arguments are startT (inclusive), and endT (exclusive). Legal values for these arguments are:
- txes (transaction entity ids)
- ts (as e.g. returned from Database.nextT)
- transaction instants (java.util.Dates)
- null (to represent the beginning/end of the log)
Each map represents a single transaction, and contains two key/value pairs.
|:t||Log.T||the transaction t|
|:data||Log.DATA||a collection of datoms|
The datoms implement the datomic.Datom interface. In Clojure, they act as both sequential and associative collections, and can be destructured accordingly.
Log in Query: tx-ids and tx-data
The log API includes two convenience functions that are available within query. The tx-ids function takes arguments similar to txRange above, but returns a collection of transaction entity ids. You will typically use the collection binding form [?tx …] to capture the results.
[(tx-ids ?log ?t1 ?tx) [?tx ...]]
The following example query returns the count of transactions within the range [t1, t2):
(d/q '[:find (count ?tx) :in $ ?log ?t1 ?t2 :where [(tx-ids ?log ?t1 ?t2) [?tx ...]]] (d/db conn) (d/log conn) t1 t2)
The tx-data function returns the datoms associated with a particular t or tx. You will typically use the relation binding form [ [?e ?a ?v _ ?op ] ] to capture the results.
[(tx-data ?log ?tx) [[?e ?a ?v _ ?op]]]
Note the underscore binding. You should not bind the ?tx position, as ?tx is already bound on input to the function.
tx-data is the efficient way to get transaction data given t or tx. A common scenario is to use tx-data in combination with tx-ids, to return the datoms associated with a range in time. The following example query returns all the entities that were modified on August 1, 2013:
(d/q '[:find ?e :in $ ?log ?t1 ?t2 :where [(tx-ids ?log ?t1 ?t2) [?tx ...]] [(tx-data ?log ?tx) [[?e]]]] (d/db conn) (d/log conn) #inst "2013-08-01" #inst "2013-08-02")