7 releases

new 0.0.7 Apr 23, 2025
0.0.6 Apr 23, 2025
0.0.4 Jun 18, 2024

#3 in #database-transaction

Download history 4/week @ 2025-01-01 4/week @ 2025-02-19 162/week @ 2025-04-16

162 downloads per month

MIT license

91KB
1.5K SLoC

Deeb - JSON Database

Call it “Deeb,” “D-b,” or “That Cool JSON Thing”—this ACID Compliant database is perfect for tiny sites and rapid experiments.

Inspired by flexibility of Mongo and light weight of SqLite, Deeb is a tool that turns a set of JSON files into a light weight database.

Deeb's ability to turn groups JSON files into a database allows you to simply open a json file and edit as needed.

Check out the quick start below, or the docs to learn more.

Quick Start

  1. Add Deeb to your Cargo.toml file
cargo add deeb
  1. Optionally, Create a JSON file for your database. Deeb will also create one for you if you like.
echo '{"user": []}' > user.json
echo '{"comment": []}' > comment.json

Terminology

  • Instance: A single .json file managed by Deeb. Each instance can store multiple entities and serves as a lightweight, self-contained database.
  • Collection: Similar to a table (SQL) or collection (MongoDB), an array of entity documents of a consistent type within an instance.
  • Entity: The type of document within a collection, for example User or Comment.
  • Document: An individual record representing an entity. Documents are stored as JSON objects and represent a single unit of data (e.g., a user, message, or task).
  1. Create a deeb instance and perform operations.
use deeb::*;
use serde_json::json;
use serde::{Serialize, Deserialize};
use anyhow::Error;

#[derive(Serialize, Deserialize)]
struct User {
    id: i32,
    name: String,
    age: i32
}

#[derive(Serialize)]
struct UpdateUser {
    name: Option<String>,
    age: Option<i32>
}

#[derive(Serialize, Deserialize)]
struct Comment {
    user_id: i32,
    comment: String
}

#[tokio::main]
async fn main() -> Result<(), Error> {
   // Create a new entity
   let user = Entity::new("user");
   let comment = Entity::new("comment");

    // Set up a new Deeb instance
   let db = Deeb::new();
   db.add_instance("test", "./user.json", vec![user.clone()])
    .await?;
   db.add_instance("test2", "./comment.json", vec![comment.clone()])
    .await?;

   // Single Operations
   db.insert::<User>(&user, User {id: 1, name: "George".to_string(), age: 10}, None).await?;
   db.find_one::<User>(&user, Query::eq("name", "George"), None).await?;

   // Perform a transaction
   let mut transaction = db.begin_transaction().await;

   // Insert data into the database
   db.insert::<User>(&user, User {id: 1, name: "Steve".to_string(), age: 3}, Some(&mut transaction)).await?;
   db.insert::<User>(&user, User {id: 2, name: "Johnny".to_string(), age: 3}, Some(&mut transaction)).await?;

   db.insert::<Comment>(&comment, Comment {user_id: 1, comment: "Hello".to_string()}, Some(&mut transaction)).await?;
   db.insert::<Comment>(&comment, Comment {user_id: 1, comment: "Hi".to_string()}, Some(&mut transaction)).await?;

   // Query the database
   let query = Query::eq("name", "Steve");
   let result = db.find_one::<User>(&user, query, Some(&mut transaction)).await?;

   // Update the database
   let query = Query::eq("name", "Steve");
   let update = UpdateUser { age: Some(5), name: None };
   db.update_one::<User, UpdateUser>(&user, query, update, Some(&mut transaction)).await?;

   // Delete from the database
   let query = Query::eq("name", "Johnny");
   db.delete_one(&user, query, Some(&mut transaction)).await?;

   db.commit(&mut transaction).await?;

   Ok(())
}

Features

  • ACID Compliant: Deeb is an ACID compliant database. We get close as we can for a light weight JSON based DB.
  • JSON-Based Storage: Deeb uses lightweight JSON files as the underlying data store, providing human-readable structure and seamless integration with any system that speaks JSON.
  • Schemaless: Deeb doesn't require a predefined schema like traditional SQL or strongly-typed NoSQL databases. However, by using Rust generics, you can enforce type safety at compile time. This means Deeb stays flexible at runtime, while giving you confidence at build time.
  • Transactions: Perform multiple operations as a single unit — commit them all at once or roll them back if something fails.
  • Querying: Deeb supports querying, nested queries, and combination queries.

Roadmap

  • Basic CRUD Operations
  • Transactions
  • Indexing
  • Querying
  • Migrations
  • Benchmarks
  • Associations
  • Documentation
  • Tests
  • Examples
  • Logging
  • Error Handling
  • CI/CD
  • Improve Transactions - Should return updated object instead of Option
  • Implement traits and proc macros to streamline usage - User.find_many(...)

Deeb

Operations

Queries

  • eq: Equal - Find documents based on exact match.
  • like: Like - Find documents based on like match.
  • ne: Not Equal - Find documents based on not equal match.
  • gt: Greater Than - Find documents based on greater than match.
  • lt: Less Than - Find documents based on less than match.
  • gte: Greater Than or Equal - Find documents based on greater than or equal match.
  • lte: Less Than or Equal - Find documents based on less than or equal match.
  • and: And - Find documents based on multiple conditions.
  • or: Or - Find documents based on multiple conditions.
  • all: All - Return all documents.
  • associated: Associated - Find documents based on association.

Transactions

  • begin_transaction: Begin a new transaction
  • commit: Commit a transaction

Data Management

mod database; mod deeb;

pub use crate::{ database::{entity::Entity, query::Query}, deeb::Deeb, };

Dependencies

~4–10MB
~102K SLoC