KOVA
Docs

Getting started

Install Kova, start it on port 27018, insert a document, and read it back after a restart.

Each merge into main publishes a Linux x86_64 build and a container image. Both are the optimized server. The examples use mongosh, the MongoDB shell. A driver in another language sends the same commands to the same port. The server itself does not need a MongoDB installation.

Install

This downloads the current build and installs it under your home directory:

curl -fsSL -o install.sh https://github.com/mdaparte/kova/releases/latest/download/install.sh
sh install.sh

kova and kovadump land in ~/.local/bin. libkova.so lands in ~/.local/lib. The config and the sample script land in ~/.local/share/kova. If ~/.local/bin is not on PATH, the script prints the line to add.

To put the files somewhere else, download the archive and run its installer with PREFIX set:

curl -fsSL -o kova.tar.gz https://github.com/mdaparte/kova/releases/latest/download/kova-x86_64-unknown-linux-gnu.tar.gz
tar -xzf kova.tar.gz
PREFIX=/opt/kova ./kova-x86_64-unknown-linux-gnu/install.sh

The archive has a .sha256 file next to it on the same release, for checking the download.

Docker

The same build is the image ghcr.io/mdaparte/kova. The tag latest is the newest merge. A tag with the commit id is that exact build. Pages and the log stay in the volume kova.

docker run --rm -p 27018:27018 -v kova:/var/lib/kova ghcr.io/mdaparte/kova:latest

The listener inside the container is on port 27018, published on the same port of the machine. -e KOVA_PORT=27019 changes the port inside the container. Publish that port with -p 27019:27019. The rest of this page talks to 127.0.0.1:27018 either way.

The sample script is in the image at /usr/share/kova/seed-oracle.js.

docker run --rm --entrypoint cat ghcr.io/mdaparte/kova:latest /usr/share/kova/seed-oracle.js > seed-oracle.js

Start the server

Start from a directory you want to keep. Pages and the log are created in data/ there.

mkdir -p "$HOME/kova-data" && cd "$HOME/kova-data"
KOVA_CONFIG="$HOME/.local/share/kova/kova.toml" kova

The listener binds 0.0.0.0:27018. Leave that process running. A second terminal is where you send commands.

Port 27018 is deliberate, so a local MongoDB on 27017 can stay up beside Kova. Override it for one run with KOVA_PORT=27019 in front of kova. The matching client then uses that port too. KOVA_LOG_LEVEL=debug raises the log for that run.

Write the first document

Open a shell against database shop:

mongosh "mongodb://127.0.0.1:27018/shop"

Insert one order and read it back.

db.orders.insertOne({ sku: "kettle", qty: 2 })
db.orders.find({ sku: "kettle" })

Kova fills _id with an ObjectId when you omit it. The reply from insertOne includes that id. find returns the document you stored.

The same question in SQL, on the same collection:

db.runCommand({
  sql: "SELECT sku, qty FROM orders WHERE qty > 1"
})

The cursor rows are the documents DataFusion produced. One FROM. The database is the one in the connection, here shop.

Stop, start, read again

Stop the server with Ctrl-C in the terminal that runs it. Start it again with the same kova command, from the same directory.

Open the shell and run the find once more. The kettle is still there. The write was appended to the log under data/ before the insert reply, and startup replays anything a checkpoint had not folded into the pages yet.

Deleting data/ starts empty. Keep that directory if you want the documents.

Load the sample

The install includes a small company sample: employees, departments, salary grades, and a few bonuses. With the server already listening:

mongosh --quiet "mongodb://127.0.0.1:27018/db" --file "$HOME/.local/share/kova/seed-oracle.js"

That drops database db and loads it again. It also creates five indexes on emp and two views, well_paid and emp_search. Your shop database is untouched.

mongosh "mongodb://127.0.0.1:27018/db"
db.emp.find({ job: "CLERK" }, { ename: 1, sal: 1, _id: 0 })
db.runCommand({
  sql: "SELECT ename, job, sal FROM emp WHERE sal > 2000"
})

well_paid is the employees with sal above 2000. emp_search is every employee, with a text index on disk. Both are covered on the Views and Text search pages.

What to open next