java -version
This quickstart guide shows you how to set up Crux, ingest a document, and query it. In a few minutes, you will have a single Crux node that persists records to disk using an in-process RocksDB instance. This means you do not need to install RocksDB separately — it will just work out of the box.
Examples are provided in Java and Clojure. Your data will be stored on the same computer your Java or Clojure process is running. This configuration is sufficient for fault-tolerant, low-load production services. It is an easy way to get familiar with Crux in a minimal production-like environment. The section "Advanced Crux Configuration" below contains more advanced configuration options.
This guide was extracted from the "Crux-in-a-Box" guide, which has minimal (working) project examples for Clojure and Java you can see in the crux-in-a-box GitHub repo. If you prefer to see all the code at once, head there first. We also have thorough Reference Docs, if that’s your speed.
Each step below contains some advanced options in collapsible notes. You can safely ignore all of these if you just want to get up and running quickly. You can always revisit them later.
Ensure you are using Java 8 or higher:
java -version
Java: JDK 8 or higher
JDK 16 requires an extra JVM option to access JVM internals due to JEP 396. (See crux#1462.)
Clojure: Clojure 1.10.3 or higher
macOS: 10.14.3 (Mojave) or higher
MacOS 10.14.3 is a RocksDB libc
dependency for macOS users. (See rocksdb#5064.)
JDK: You may require AdoptOpenJDK on certain macOS versions. (See crux#894.)
Native Arm64 RocksDB Java is currently unspported on Apple M1 processors, causing an UnsatisfiedLinkError
. M1 users can still run an x86 JVM on Rosetta, however. (See rocksdb#7720.)
Linux: No known version constraints
Windows: No known version constraints
Add Crux to your Clojure or Java project:
juxt/crux-core {:mvn/version "{crux_version}-beta"}
juxt/crux-rocksdb {:mvn/version "{crux_version}-beta"}
[juxt/crux-core "{crux_version}-beta"]
[juxt/crux-rocksdb "{crux_version}-beta"]
<dependency>
<groupId>juxt</groupId>
<artifactId>crux-core</artifactId>
<version>{crux_version}-beta</version>
</dependency>
<dependency>
<groupId>juxt</groupId>
<artifactId>crux-rocksdb</artifactId>
<version>{crux_version}-beta</version>
</dependency>
Without setting up logging, you will see a SLF4J: Defaulting to no-operation (NOP) logger implementation
message on STDOUT from Crux. This is harmless, but in a real application you will want to configure Logback
with the SLF4J API to see INFO messages from Crux.
To do this in Clojure:
Set the clojure.tools.logging.factory
JVM option
Create a crux-in-a-box/resources/logback.xml
file
To do this in Java:
The following configuration uses an in-process RocksDB instance to write your data to disk. It will save your data in a directory named ./data/dev
, relative to your project root. You do not need to create this directory. Crux will create it for you.
(ns crux-in-a-box.db
(:require [clojure.java.io :as io]
[crux.api :as crux]))
(defn start-crux! []
(letfn [(kv-store [dir]
{:kv-store {:crux/module 'crux.rocksdb/->kv-store
:db-dir (io/file dir)
:sync? true}})]
(crux/start-node
{:crux/tx-log (kv-store "data/dev/tx-log")
:crux/document-store (kv-store "data/dev/doc-store")
:crux/index-store (kv-store "data/dev/index-store")})))
(def crux-node (start-crux!))
(defn stop-crux! []
(.close crux-node))
package cruxinabox;
import java.io.File;
import java.io.IOException;
import crux.api.Crux;
import crux.api.ICruxAPI;
import java.util.HashMap;
import java.util.List;
import crux.api.ICruxDatasource;
import crux.api.ICursor;
import crux.api.CruxDocument;
import crux.api.TransactionInstant;
import crux.api.tx.Transaction;
class Box {
public static void main(String[] args) {
try(ICruxAPI cruxNode = Crux.startNode(new File("config.json"))) {
System.out.println("Crux Started.");
// ... ingest goes here
// ... query goes here
}
catch (IOException e) {
// ...
}
}
}
{
"crux/index-store": {
"kv-store": {
"crux/module": "crux.rocksdb/->kv-store",
"db-dir": "data/index-store"
}
},
"crux/document-store": {
"kv-store": {
"crux/module": "crux.rocksdb/->kv-store",
"db-dir": "data/doc-store"
}
},
"crux/tx-log": {
"kv-store": {
"crux/module": "crux.rocksdb/->kv-store",
"db-dir": "data/tx-log"
}
},
"crux.lucene/lucene-store": {
"db-dir": "data/dev/lucene-dir"
},
"crux.http-server/server": {
"port": 9999
}
}
This guide also does not make any assumptions about how you manage stateful services. Crux is a stateful service, however, and you should store the Crux node in your favourite state management library. In Clojure, you might use Mount.
Transaction Log
Document Store
Index Store
For more advanced configuration, Crux allows you to choose the underlying data storage technology (for each of the three components) from a number of different modules. The Reference Docs contain a list of available modules, each with instructions on how to configure them.
crux-in-a-box.db> (crux/submit-tx crux-node [[:crux.tx/put
{:crux.db/id "hi2u"
:user/name "zig"}]])
;; => #:crux.tx{:tx-id 0, :tx-time #inst "2021-03-11T02:27:09.176-00:00"}
HashMap<String, Object> data = new HashMap<>();
data.put("user/name", "zig");
CruxDocument document = CruxDocument.create("hi2u", data);
TransactionInstant transaction = node.submitTx(Transaction.buildTx(tx -> {
tx.put(document);
}));
System.out.println(data.toString());
crux-in-a-box.db> (crux/q (crux/db crux-node) '{:find [e]
:where [[e :user/name "zig"]]} )
;; => #{["hi2u"]}
crux-in-a-box.db> (stop-crux!)
;; => nil
String query = "{:find [e] :where [[e :user/name \"zig\"]]}";
ICruxDatasource 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();
Crux requires very little effort to set up and start using immediately. Now that you are comfortable with the basics, you can read through the Reference Docs or try the Tutorial. We also have Articles and blog posts talking about the philosophy and history of Crux. If you are feeling particularly excited, you can browse our Bibliography.
As always, we encourage you to chat with us on Zulip or #crux
on
Clojurians if you have questions or ideas. Enjoy Crux!
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close