API Documentation

Every OxiDB command with examples in Rust, Python, Go, and .NET. Click a language tab to switch.

Connection

Connect / Open

Open a database connection. TCP mode connects to a server; embedded mode opens files directly.

use oxidb::OxiDb;

// Embedded — opens database files at the given path
let db = OxiDb::open("./my_data").unwrap();

// With encryption
let db = OxiDb::open_encrypted("./my_data", "./key.bin").unwrap();
from oxidb import OxiDbClient

# TCP client — connects to oxidb-server
client = OxiDbClient("127.0.0.1", 4444)

# With timeout
client = OxiDbClient("127.0.0.1", 4444, timeout=10.0)

# Context manager
with OxiDbClient() as db:
    db.ping()
from oxidb_embedded import OxiDbEmbedded

# Embedded — no server required
db = OxiDbEmbedded("./my_data")

# With encryption
db = OxiDbEmbedded("./my_data", encryption_key_path="./key.bin")

# Context manager
with OxiDbEmbedded("./my_data") as db:
    db.ping()
client, err := oxidb.Connect("127.0.0.1", 4444)
// or
client, err := oxidb.ConnectDefault() // localhost:4444

// Enable binary protocol (faster)
client.UseOxiWire()

defer client.Close()
// TCP client
var client = new OxiDbTcpClient("127.0.0.1", 4444);

// Embedded client
var client = new OxiDbEmbeddedClient("./my_data");

// EF Core
builder.Services.AddOxiDb(options => {
    options.UseTcp("127.0.0.1", 4444);
    // or: options.UseEmbedded("./data");
});

Close

Close the database connection and free resources.

// Dropped automatically when out of scope
drop(db);
client.close()
# or use context manager: with OxiDbClient() as db: ...
client.Close()
client.Dispose();
// or: using var client = new OxiDbTcpClient(...);

Ping

Check that the database is reachable. Returns "pong".

let pong = db.ping(); // "pong"
result = client.ping()  # "pong"
result, err := client.Ping() // "pong"
var result = await client.PingAsync(); // "pong"

Collections

Create Collection

Explicitly create a collection. Collections are also auto-created on first insert.

db.create_collection("users").unwrap();
client.create_collection("users")
err := client.CreateCollection("users")
await client.CreateCollectionAsync("users");

List Collections

let names = db.list_collections(); // Vec<String>
names = client.list_collections()  # ["users", "orders"]
names, err := client.ListCollections() // []string
var names = await client.ListCollectionsAsync();

Drop Collection

Delete a collection and all its data.

db.drop_collection("temp").unwrap();
client.drop_collection("temp")
err := client.DropCollection("temp")
await client.DropCollectionAsync("temp");

CRUD Operations

Insert

Insert a single document. Returns the generated _id. Collection is auto-created if it doesn't exist.

let id = db.insert("users", json!({
    "name": "Alice",
    "age": 30,
    "email": "[email protected]"
})).unwrap();
result = client.insert("users", {
    "name": "Alice",
    "age": 30,
    "email": "[email protected]",
})
# result: {"id": 1}
result, err := client.Insert("users", map[string]any{
    "name":  "Alice",
    "age":   30,
    "email": "[email protected]",
})
var result = await client.InsertAsync("users", new {
    name = "Alice",
    age = 30,
    email = "[email protected]"
});

Insert Many

Insert multiple documents in a single call.

let docs = vec![
    json!({"name": "Bob", "age": 25}),
    json!({"name": "Charlie", "age": 35}),
];
db.insert_many("users", docs).unwrap();
client.insert_many("users", [
    {"name": "Bob", "age": 25},
    {"name": "Charlie", "age": 35},
])
err := client.InsertMany("users", []any{
    map[string]any{"name": "Bob", "age": 25},
    map[string]any{"name": "Charlie", "age": 35},
})
await client.InsertManyAsync("users", new[] {
    new { name = "Bob", age = 25 },
    new { name = "Charlie", age = 35 },
});

Find

Query documents with filters, sort, skip, and limit.

// Simple query
let users = db.find("users", json!({"age": {"$gt": 25}}), None).unwrap();

// With sort, skip, limit
let opts = json!({"sort": {"age": -1}, "skip": 0, "limit": 10});
let users = db.find("users", json!({}), Some(opts)).unwrap();
# Simple query
users = client.find("users", {"age": {"$gt": 25}})

# With sort, skip, limit
users = client.find("users", {},
    sort={"age": -1},
    skip=0,
    limit=10,
)
// Simple query
users, err := client.Find("users", map[string]any{
    "age": map[string]any{"$gt": 25},
}, nil)

// With options
users, err := client.Find("users", map[string]any{}, &oxidb.FindOptions{
    Sort:  map[string]any{"age": -1},
    Skip:  0,
    Limit: 10,
})
// Simple query
var users = await client.FindAsync("users", new { age = new { _gt = 25 } });

// EF Core LINQ
var users = await db.Users
    .Where(u => u.Age > 25)
    .OrderByDescending(u => u.Age)
    .Skip(0).Take(10)
    .ToListAsync();

Find One

Return the first matching document, or null/None if none match.

let user = db.find_one("users", json!({"name": "Alice"})).unwrap();
user = client.find_one("users", {"name": "Alice"})
user, err := client.FindOne("users", map[string]any{"name": "Alice"})
var user = await client.FindOneAsync("users", new { name = "Alice" });

Count

Count documents matching a query. Uses index-only path when possible.

let total = db.count("users", json!({})).unwrap();
let adults = db.count("users", json!({"age": {"$gte": 18}})).unwrap();
total = client.count("users")
adults = client.count("users", {"age": {"$gte": 18}})
total, err := client.Count("users", nil)
adults, err := client.Count("users", map[string]any{"age": map[string]any{"$gte": 18}})
var total = await client.CountAsync("users");
var adults = await client.CountAsync("users", new { age = new { _gte = 18 } });

Update

Update all documents matching a query. Supports $set, $unset, $inc, $mul, $min, $max, $rename, $currentDate, $push, $pull, $addToSet, $pop.

db.update("users",
    json!({"status": "pending"}),
    json!({"$set": {"status": "active"}, "$inc": {"login_count": 1}}),
).unwrap();
client.update("users",
    {"status": "pending"},
    {"$set": {"status": "active"}, "$inc": {"login_count": 1}},
)
result, err := client.Update("users",
    map[string]any{"status": "pending"},
    map[string]any{"$set": map[string]any{"status": "active"}, "$inc": map[string]any{"login_count": 1}},
)
await client.UpdateAsync("users",
    new { status = "pending" },
    new { _set = new { status = "active" }, _inc = new { login_count = 1 } });

Update One

Update the first matching document. Stops after first match (early termination).

db.update_one("users",
    json!({"name": "Alice"}),
    json!({"$set": {"age": 31}}),
).unwrap();
client.update_one("users", {"name": "Alice"}, {"$set": {"age": 31}})
result, err := client.UpdateOne("users",
    map[string]any{"name": "Alice"},
    map[string]any{"$set": map[string]any{"age": 31}},
)
await client.UpdateOneAsync("users",
    new { name = "Alice" },
    new { _set = new { age = 31 } });

Delete

Delete all documents matching a query.

db.delete("users", json!({"age": {"$lt": 18}})).unwrap();
client.delete("users", {"age": {"$lt": 18}})
result, err := client.Delete("users", map[string]any{"age": map[string]any{"$lt": 18}})
await client.DeleteAsync("users", new { age = new { _lt = 18 } });

Delete One

Delete the first matching document.

db.delete_one("users", json!({"name": "Charlie"})).unwrap();
client.delete_one("users", {"name": "Charlie"})
result, err := client.DeleteOne("users", map[string]any{"name": "Charlie"})
await client.DeleteOneAsync("users", new { name = "Charlie" });

Indexes

Create Index

Create a B-tree index on a single field. Speeds up equality, range, and sort queries.

db.create_index("users", "age").unwrap();
client.create_index("users", "age")
err := client.CreateIndex("users", "age")
await client.CreateIndexAsync("users", "age");

Create Unique Index

Enforces uniqueness on the field. Inserts with duplicate values will fail.

db.create_unique_index("users", "email").unwrap();
client.create_unique_index("users", "email")
err := client.CreateUniqueIndex("users", "email")
await client.CreateUniqueIndexAsync("users", "email");

Create Composite Index

Multi-field B-tree index for prefix scans.

db.create_composite_index("orders", &["user_id", "status"]).unwrap();
client.create_composite_index("orders", ["user_id", "status"])
err := client.CreateCompositeIndex("orders", []string{"user_id", "status"})
await client.CreateCompositeIndexAsync("orders", new[] { "user_id", "status" });

Create Text Index

Full-text search index on one or more fields. Supports TF-IDF ranking.

db.create_text_index("articles", &["title", "body"]).unwrap();
client.create_text_index("articles", ["title", "body"])
err := client.CreateTextIndex("articles", []string{"title", "body"})
await client.CreateTextIndexAsync("articles", new[] { "title", "body" });

List Indexes

let indexes = db.list_indexes("users").unwrap();
indexes = client.list_indexes("users")
indexes, err := client.ListIndexes("users")
var indexes = await client.ListIndexesAsync("users");

Drop Index

db.drop_index("users", "idx_age").unwrap();
client.drop_index("users", "idx_age")
err := client.DropIndex("users", "idx_age")
await client.DropIndexAsync("users", "idx_age");

Aggregation

Aggregate

Run an aggregation pipeline. Stages: $match, $group, $sort, $project, $limit, $skip, $unwind, $addFields, $lookup, $count.

Group accumulators: $sum, $avg, $min, $max, $first, $last.

let results = db.aggregate("orders", vec![
    json!({"$match": {"status": "delivered"}}),
    json!({"$group": {
        "_id": "$customer",
        "total": {"$sum": "$amount"},
        "count": {"$sum": 1},
    }}),
    json!({"$sort": {"total": -1}}),
    json!({"$limit": 10}),
]).unwrap();
results = client.aggregate("orders", [
    {"$match": {"status": "delivered"}},
    {"$group": {
        "_id": "$customer",
        "total": {"$sum": "$amount"},
        "count": {"$sum": 1},
    }},
    {"$sort": {"total": -1}},
    {"$limit": 10},
])
results, err := client.Aggregate("orders", []any{
    map[string]any{"$match": map[string]any{"status": "delivered"}},
    map[string]any{"$group": map[string]any{
        "_id": "$customer",
        "total": map[string]any{"$sum": "$amount"},
        "count": map[string]any{"$sum": 1},
    }},
    map[string]any{"$sort": map[string]any{"total": -1}},
    map[string]any{"$limit": 10},
})
var results = await client.AggregateAsync("orders", new object[] {
    new { _match = new { status = "delivered" } },
    new { _group = new { _id = "$customer", total = new { _sum = "$amount" } } },
    new { _sort = new { total = -1 } },
    new { _limit = 10 },
});

Transactions

OCC (Optimistic Concurrency Control) with 3-phase commit. Writes are buffered until commit. Deadlock-free via sorted collection locking.

Begin Transaction

db.begin_transaction().unwrap();
client.begin_tx()
err := client.BeginTx()
await client.BeginTxAsync();

Commit Transaction

db.commit_transaction().unwrap();
client.commit_tx()
err := client.CommitTx()
await client.CommitTxAsync();

Rollback Transaction

db.rollback_transaction().unwrap();
client.rollback_tx()
err := client.RollbackTx()
await client.RollbackTxAsync();

Transaction Context Manager

Auto-commits on success, auto-rolls back on exception.

db.transaction(|tx| {
    tx.insert("accounts", json!({"owner": "Alice", "balance": 1000}))?;
    tx.update_one("accounts",
        json!({"owner": "Bob"}),
        json!({"$inc": {"balance": -500}}),
    )?;
    Ok(())
}).unwrap();
with client.transaction():
    client.insert("accounts", {"owner": "Alice", "balance": 1000})
    client.update_one("accounts",
        {"owner": "Bob"},
        {"$inc": {"balance": -500}},
    )
# auto-committed here; rolls back on exception
err := client.WithTransaction(func() error {
    client.Insert("accounts", map[string]any{"owner": "Alice", "balance": 1000})
    client.UpdateOne("accounts",
        map[string]any{"owner": "Bob"},
        map[string]any{"$inc": map[string]any{"balance": -500}},
    )
    return nil
})
await client.TransactionAsync(async () => {
    await client.InsertAsync("accounts", new { owner = "Alice", balance = 1000 });
    await client.UpdateOneAsync("accounts",
        new { owner = "Bob" },
        new { _inc = new { balance = -500 } });
});

SQL

Execute SQL

Run SQL queries. Supports SELECT, INSERT, UPDATE, DELETE, CREATE INDEX, CREATE TABLE, JOINs, GROUP BY, ORDER BY.

use oxidb::sql::execute_sql;

let result = execute_sql(&db, "SELECT * FROM users WHERE age > 25 ORDER BY name").unwrap();
execute_sql(&db, "INSERT INTO users (name, age) VALUES ('Eve', 22)").unwrap();
execute_sql(&db, "UPDATE users SET age = 31 WHERE name = 'Alice'").unwrap();
execute_sql(&db, "DELETE FROM users WHERE age < 18").unwrap();
execute_sql(&db, "CREATE INDEX idx_age ON users (age)").unwrap();
result = client.sql("SELECT * FROM users WHERE age > 25 ORDER BY name")
client.sql("INSERT INTO users (name, age) VALUES ('Eve', 22)")
client.sql("UPDATE users SET age = 31 WHERE name = 'Alice'")
client.sql("DELETE FROM users WHERE age < 18")

# JOINs
result = client.sql("""
    SELECT u.name, COUNT(o._id) as order_count
    FROM users u JOIN orders o ON u._id = o.user_id
    GROUP BY u.name ORDER BY order_count DESC
""")
result, err := client.SQL("SELECT * FROM users WHERE age > 25 ORDER BY name")
client.SQL("INSERT INTO users (name, age) VALUES ('Eve', 22)")
client.SQL("UPDATE users SET age = 31 WHERE name = 'Alice'")
client.SQL("DELETE FROM users WHERE age < 18")
var result = await client.SqlAsync("SELECT * FROM users WHERE age > 25 ORDER BY name");

// EF Core LINQ (compiles to queries internally)
var users = await db.Users
    .Where(u => u.Age > 25)
    .OrderBy(u => u.Name)
    .ToListAsync();

Search

Vector Search

Create Vector Index

Create an HNSW vector index. Distance metrics: cosine, euclidean, dot_product.

use oxidb::vector::DistanceMetric;
db.create_vector_index("products", "embedding", 384, DistanceMetric::Cosine).unwrap();
client.create_vector_index("products", "embedding", dimension=384, metric="cosine")
err := client.CreateVectorIndex("products", "embedding", 384, "cosine")
await client.CreateVectorIndexAsync("products", "embedding", 384, "cosine");

Blob Storage

S3-style object storage. Store files, PDFs, images with metadata. CRC32 etags.

Create Bucket

db.create_bucket("documents").unwrap();
client.create_bucket("documents")
err := client.CreateBucket("documents")
await client.CreateBucketAsync("documents");

List Buckets

let buckets = db.list_buckets().unwrap();
buckets = client.list_buckets()
buckets, err := client.ListBuckets()
var buckets = await client.ListBucketsAsync();

Delete Bucket

db.delete_bucket("documents").unwrap();
client.delete_bucket("documents")
err := client.DeleteBucket("documents")
await client.DeleteBucketAsync("documents");

Put Object

Upload a file/blob with content type and optional metadata.

let data = std::fs::read("report.pdf").unwrap();
db.put_object("documents", "report.pdf", &data,
    "application/pdf", Some(json!({"author": "Alice"}))).unwrap();
with open("report.pdf", "rb") as f:
    client.put_object("documents", "report.pdf", f.read(),
        content_type="application/pdf",
        metadata={"author": "Alice"})
data, _ := os.ReadFile("report.pdf")
err := client.PutObject("documents", "report.pdf", data,
    "application/pdf", map[string]string{"author": "Alice"})
var data = await File.ReadAllBytesAsync("report.pdf");
await client.PutObjectAsync("documents", "report.pdf", data,
    "application/pdf", new { author = "Alice" });

Get Object

Download a blob. Returns the data and metadata.

let (data, meta) = db.get_object("documents", "report.pdf").unwrap();
data, metadata = client.get_object("documents", "report.pdf")
data, meta, err := client.GetObject("documents", "report.pdf")
var (data, meta) = await client.GetObjectAsync("documents", "report.pdf");

Head Object

Get metadata without downloading the data.

let meta = db.head_object("documents", "report.pdf").unwrap();
meta = client.head_object("documents", "report.pdf")
meta, err := client.HeadObject("documents", "report.pdf")
var meta = await client.HeadObjectAsync("documents", "report.pdf");

Delete Object

db.delete_object("documents", "report.pdf").unwrap();
client.delete_object("documents", "report.pdf")
err := client.DeleteObject("documents", "report.pdf")
await client.DeleteObjectAsync("documents", "report.pdf");

List Objects

List objects in a bucket with optional prefix filter.

let objects = db.list_objects("documents", Some("reports/"), None).unwrap();
objects = client.list_objects("documents", prefix="reports/")
objects, err := client.ListObjects("documents", "reports/", 0)
var objects = await client.ListObjectsAsync("documents", prefix: "reports/");

Maintenance

Compact

Reclaim disk space by removing soft-deleted records. Returns old/new size and docs kept.

let stats = db.compact("users").unwrap();
// stats.old_size, stats.new_size, stats.docs_kept
stats = client.compact("users")
# {"old_size": 102400, "new_size": 81920, "docs_kept": 500}
stats, err := client.Compact("users")
// stats["old_size"], stats["new_size"], stats["docs_kept"]
var stats = await client.CompactAsync("users");