Skip to main content
This quickstart guide will help you create your first jasonisnthappy database and perform basic CRUD operations. We’ll use Rust for this example, but jasonisnthappy works with Go, Python, and JavaScript too.

Prerequisites

  • Rust 1.70 or later (for Rust usage)
  • Basic familiarity with JSON documents
If you’re using Go, Python, or JavaScript, see the Installation guide for language-specific setup instructions.

Installation

Add jasonisnthappy to your Cargo.toml:
Cargo.toml
[dependencies]
jasonisnthappy = "0.1.1"
serde_json = "1.0"

Create your first database

Here’s a complete example that demonstrates the core features of jasonisnthappy:
1

Open a database

Create or open a database file. If the file doesn’t exist, jasonisnthappy will create it.
examples/collection_crud.rs
use jasonisnthappy::core::database::Database;
use serde_json::json;
use std::sync::Arc;

let db = Arc::new(Database::open("crud_example.db")?);
let users = db.collection("users");
The database file stores all your data. Additional files like .lock and -wal (write-ahead log) are created automatically for concurrency control and durability.
2

Insert documents

Add JSON documents to a collection. Collections are created automatically when you first use them.
examples/collection_crud.rs
let alice = json!({"name": "Alice", "age": 30, "city": "New York"});
let bob = json!({"name": "Bob", "age": 25, "city": "San Francisco"});
let charlie = json!({"name": "Charlie", "age": 35, "city": "Seattle"});

let id1 = users.insert(alice)?;
let id2 = users.insert(bob)?;
let id3 = users.insert(charlie)?;

println!("Inserted Alice: {}", id1);
println!("Inserted Bob: {}", id2);
println!("Inserted Charlie: {}", id3);
Each document is automatically assigned a unique ID that’s returned from the insert() operation.
3

Query documents

Retrieve documents by ID or count all documents in a collection.
examples/collection_crud.rs
// Count total documents
let count = users.count()?;
println!("Total documents: {}", count);

// Find by ID
let found = users.find_by_id(&id1)?;
println!("Found: {}", serde_json::to_string_pretty(&found)?);

// Find all documents
let all_users = users.find_all()?;
for user in &all_users {
    println!("- {}", user["name"]);
}
4

Update documents

Modify existing documents using their ID.
examples/collection_crud.rs
// Update Alice's age
users.update_by_id(&id1, json!({"age": 31}))?;
let updated = users.find_by_id(&id1)?;
println!("Updated age: {}", updated["age"]);
Updates are partial by default - only the fields you specify are changed.
5

Delete documents

Remove documents from a collection.
examples/collection_crud.rs
// Delete Bob
users.delete_by_id(&id2)?;
let count_after_delete = users.count()?;
println!("Documents after delete: {}", count_after_delete);
6

Close the database

Always close the database when you’re done to ensure all data is flushed to disk.
examples/collection_crud.rs
db.close()?;

Working with transactions

For operations that need atomicity, use explicit transactions. This example shows how to perform multiple operations that either all succeed or all fail together:
examples/basic_usage.rs
use jasonisnthappy::core::database::Database;

let db = Database::open("example.db")?;

// Begin a transaction
let mut tx = db.begin()?;

// Write documents within the transaction
tx.write_document("users", "user1", 100)?;
tx.write_document("users", "user2", 101)?;

// Commit to make changes permanent
tx.commit()?;

db.close()?;
If you don’t call commit(), the transaction will be automatically rolled back when it goes out of scope, discarding all changes.

Understanding MVCC

One of jasonisnthappy’s key features is MVCC (Multi-Version Concurrency Control), which allows:
  • Concurrent reads: Multiple readers can access data simultaneously without blocking
  • Non-blocking writes: Writers don’t block readers and vice versa
  • Snapshot isolation: Each transaction sees a consistent snapshot of the database
This happens automatically - you don’t need to manage locks or worry about read/write conflicts in most cases.

Explore the Web UI

jasonisnthappy includes a built-in web interface for exploring your data:
examples/web_ui_demo.rs
use jasonisnthappy::Database;

let db = Database::open("web_demo.db")?;

// Start the web UI on port 8080
let _web_server = db.start_web_ui("127.0.0.1:8080")?;

println!("Web UI running at http://127.0.0.1:8080");

// Keep server alive
std::thread::park();
The Web UI provides:
  • Collection browser with document viewer
  • Real-time metrics dashboard
  • Search and pagination
  • Auto-refresh every 5 seconds
The Web UI is perfect for development and debugging. You can inspect your data, test queries, and monitor database performance in real-time.

Next steps

Now that you’ve created your first database, explore these topics:

Installation guide

Install jasonisnthappy for Go, Python, or JavaScript

Core concepts

Learn about transactions, collections, and MVCC in depth

Querying data

Master the query language and aggregation pipeline

Indexing

Optimize performance with B-tree and full-text indexes

Complete example

Here’s the full working example from the source repository:
examples/collection_crud.rs
use jasonisnthappy::core::database::Database;
use serde_json::json;
use std::sync::Arc;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("=== Collection CRUD Example ==="\n);

    let _ = std::fs::remove_file("crud_example.db");
    let _ = std::fs::remove_file("crud_example.db.lock");
    let _ = std::fs::remove_file("crud_example.db-wal");

    let db = Arc::new(Database::open("crud_example.db")?);
    let users = db.collection("users");

    println!("1. Inserting documents...");
    let alice = json!({"name": "Alice", "age": 30, "city": "New York"});
    let bob = json!({"name": "Bob", "age": 25, "city": "San Francisco"});
    let charlie = json!({"name": "Charlie", "age": 35, "city": "Seattle"});

    let id1 = users.insert(alice)?;
    let id2 = users.insert(bob)?;
    let id3 = users.insert(charlie)?;

    println!("   Inserted Alice: {}", id1);
    println!("   Inserted Bob: {}", id2);
    println!("   Inserted Charlie: {}", id3);

    println!("\n2. Counting documents...");
    let count = users.count()?;
    println!("   Total documents: {}", count);

    println!("\n3. Finding document by ID...");
    let found = users.find_by_id(&id1)?;
    println!("   Found: {}", serde_json::to_string_pretty(&found)?);

    println!("\n4. Finding all documents...");
    let all_users = users.find_all()?;
    for user in &all_users {
        println!("   - {}", user["name"]);
    }

    println!("\n5. Updating Alice's age...");
    users.update_by_id(&id1, json!({"age": 31}))?;
    let updated = users.find_by_id(&id1)?;
    println!("   Updated age: {}", updated["age"]);

    println!("\n6. Deleting Bob...");
    users.delete_by_id(&id2)?;
    let count_after_delete = users.count()?;
    println!("   Documents after delete: {}", count_after_delete);

    println!("\n7. Remaining documents:");
    let remaining = users.find_all()?;
    for user in &remaining {
        println!("   - {} (age {})", user["name"], user["age"]);
    }

    db.close()?;

    println!("\n8. Cleaning up...");
    std::fs::remove_file("crud_example.db")?;
    std::fs::remove_file("crud_example.db.lock")?;
    std::fs::remove_file("crud_example.db-wal")?;

    println!("\n=== Example Complete ===");

    Ok(())
}
Run this example with:
cargo run --example collection_crud

Build docs developers (and LLMs) love