java -version
This guide will show you how to set up XTDB with the following properties:
Disk: Records persist to disk
One node: Only one XTDB node is configured
Storage: RocksDB is used for all 3 stores (tx-log, doc-store, and index-store)
This guide will not discuss high-availability, failover/clustering/replication, or backups. You can use this simple RocksDB configuration in production and back it up as you would any other volume. If you want more advanced features, however, you should consider the Kafka and/or JDBC modules.
All the code from this guide is compiled into minimal (working) project examples for Clojure and Java you can see in the crux-in-a-box GitHub repo.
Ensure you are using Java 8 or higher:
java -version
Add XTDB to your Clojure or Java project:
com.xtdb/xtdb-core {:mvn/version "{xtdb_version}"}
com.xtdb/xtdb-rocksdb {:mvn/version "{xtdb_version}"}
[com.xtdb/xtdb-core "{xtdb_version}"]
[com.xtdb/xtdb-rocksdb "{xtdb_version}"]
<dependency>
<groupId>com.xtdb</groupId>
<artifactId>xtdb-core</artifactId>
<version>{xtdb_version}</version>
</dependency>
<dependency>
<groupId>com.xtdb</groupId>
<artifactId>xtdb-rocksdb</artifactId>
<version>{xtdb_version}</version>
</dependency>
A Note on Logging Ignore this note if you just want to get up and running quickly. It’s completely optional, but nice to have. Without setting up logging, you will see a To do this in Clojure:
To do this in Java: |
This guide gets you up and running quickly by hard-coding configuration values. Store these configuration values with your favourite configuration library. In Clojure, you might use Aero.
This guide also does not make any assumptions about how you manage stateful services. XTDB is a stateful service, however, and you should store the XTDB node in your favourite state management library. In Clojure, you might use Mount.
(ns xtdb-in-a-box.db
(:require [clojure.java.io :as io]
[xtdb.api :as xt]))
(defn start-xtdb! []
(letfn [(kv-store [dir]
{:kv-store {:xtdb/module 'xtdb.rocksdb/->kv-store
:db-dir (io/file dir)
:sync? true}})]
(xt/start-node
{:xtdb/tx-log (kv-store "data/dev/tx-log")
:xtdb/document-store (kv-store "data/dev/doc-store")
:xtdb/index-store (kv-store "data/dev/index-store")})))
(def xtdb-node (start-xtdb!))
(defn stop-xtdb! []
(.close xtdb-node))
package xtdbinabox;
import java.io.File;
import java.io.IOException;
import xtdb.api.IXtdb;
class Box {
public static void main(String[] args) {
try(IXtdb xtdbNode = IXtdb.startNode(new File("config.json"))) {
System.out.println("XTDB Started.");
}
catch (IOException e) {
// ...
}
}
}
{
"xtdb/index-store": {
"kv-store": {
"xtdb/module": "xtdb.rocksdb/->kv-store",
"db-dir": "data/index-store"
}
},
"xtdb/document-store": {
"kv-store": {
"xtdb/module": "xtdb.rocksdb/->kv-store",
"db-dir": "data/doc-store"
}
},
"xtdb/tx-log": {
"kv-store": {
"xtdb/module": "xtdb.rocksdb/->kv-store",
"db-dir": "data/tx-log"
}
},
"xtdb.lucene/lucene-store": {
"db-dir": "data/dev/lucene-dir"
},
"xtdb.http-server/server": {
"port": 9999
}
}
Time to play with your new XTDB node. Try inserting some data, query it back out, and then shut down your node. This guide is not meant to teach you Datalog, the XTDB API, or XTDB query semantics — you can look through the Tutorial and Reference Docs to dig deeper. But you should note that XTDB is asynchronous by default. That means submit-tx
returns immediately, even if your document hasn’t been indexed yet. It’s unlikely your query will come back empty, but don’t be shocked if it does. Just try it again.
xtdb-in-a-box.db> (xt/submit-tx xtdb-node [[::xt/put
{:xt/id "hi2u"
:user/name "zig"}]])
;; => #::xt{:tx-id 0, :tx-time #inst "2021-03-11T02:27:09.176-00:00"}
xtdb-in-a-box.db> (xt/q (xt/db xtdb-node) '{:find [e]
:where [[e :user/name "zig"]]} )
;; => #{["hi2u"]}
xtdb-in-a-box.db> (stop-xtdb!)
;; => nil
/* include these imports in addition to those you used to configure XTDB: */
import java.util.HashMap;
import java.util.List;
import xtdb.api.IXtdbDatasource;
import xtdb.api.ICursor;
import xtdb.api.XtdbDocument;
import xtdb.api.TransactionInstant;
import xtdb.api.tx.Transaction;
/* submitTx example: */
HashMap<String, Object> data = new HashMap<>();
data.put("user/name", "zig");
XtdbDocument document = XtdbDocument.create("hi2u", data);
TransactionInstant transaction = node.submitTx(Transaction.buildTx(tx -> {
tx.put(document);
}));
System.out.println(data.toString());
/* query example: */
node.awaitTx(transaction, null);
String query = "{:find [e] :where [[e :user/name \"zig\"]]}";
IXtdbDatasource db = node.db();
ICursor<List<?>> results = db.openQuery(query);
if (results.hasNext()) {
List<?> result = results.next();
System.out.println(result.toString());
}
db.close();
node.close();
This is a simple XTDB setup with a small footprint. You could use this setup to build a small greenfield project or replace an existing Postgres, MySQL, or MongoDB installation which currently supports CRUD or reference data. With XTDB, that database can grow with you. When it eventually requires streaming, replication, or high availability, you can migrate from RocksDB to Kafka or JDBC. But you don’t need to involve those modules up-front unless you’re sure you need them.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close