deeb/lib.rs
1//! # Deeb - JSON Database
2//!
3//! Call it "Deeb," "D-b," or "That Cool JSON Thing"—this ACID Compliant database
4//! is perfect for tiny sites and rapid experiments.
5//!
6//! Inspired by flexibility of Mongo and light weight of SqLite, Deeb is a tool
7//! that turns a set of JSON files into a light weight database.
8//!
9//! Deeb's ability to turn groups JSON files into a database allows you to simply
10//! open a json file and edit as needed.
11//!
12//! The new Deeb Docs site is available now at www.deebkit.com << Check it out
13//!
14//! -- or --
15//!
16//! Check out the quick start below, or the [docs](https://docs.rs/deeb/latest/deeb/)
17//! to learn more.
18//!
19//! ## Quick Start
20//!
21//! 1. Add Deeb to your `Cargo.toml` file
22//!
23//! ```bash
24//! cargo add deeb
25//! ```
26//!
27//! 2. Optionally, Create a JSON file for your database. Deeb will also create one for you if it does not exist.
28//!
29//! ```bash
30//! echo '{"user": []}' > user.json
31//! echo '{"comment": []}' > comment.json
32//! ```
33//!
34//! **Terminology**
35//! - Instance: A single .json file managed by Deeb. Each instance can store multiple entities and serves as a lightweight, self-contained database.
36//! - Collection: Similar to a table (SQL) or collection (MongoDB), an array of entity documents of a consistent type within an instance.
37//! - Entity: The `type` of document within a collection, for example User or Comment.
38//! - 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).
39//!
40//! 3. Create a deeb instance and perform operations.
41//!
42//! ```rust
43//! use deeb::*;
44//! use serde_json::json;
45//! use serde::{Serialize, Deserialize};
46//! use anyhow::Error;
47//!
48//! #[derive(Collection, Serialize, Deserialize)]
49//! #[deeb(
50//! name = "user",
51//! primary_key = "id",
52//! associate = ("comment", "id", "user_id", "user_comment"),
53//! )]
54//! struct User {
55//! id: i32,
56//! name: String,
57//! age: i32
58//! }
59//!
60//! #[derive(Collection, Serialize, Deserialize)]
61//! #[deeb(name = "comment", primary_key = "_id")]
62//! struct Comment {
63//! user_id: i32,
64//! comment: String
65//! }
66//!
67//! #[tokio::main]
68//! async fn main() -> Result<(), Error> {
69//! // Create Entities
70//! let mut user = User::entity();
71//! user.add_index("age_index", vec!["age"], None)?;
72//! let comment = Comment::entity();
73//!
74//! // Set up a new Deeb instance
75//! let db = Deeb::new();
76//! db.add_instance("test-lib", "./user.json", vec![user.clone()])
77//! .await?;
78//! db.add_instance("test-lib2", "./comment.json", vec![comment.clone()])
79//! .await?;
80//!
81//! // Single Operations
82//! User::insert_one(&db, User {id: 1, name: "George".to_string(), age: 10}, None).await?;
83//! User::find_one(&db, Query::eq("name", "George"), None).await?;
84//!
85//! // Perform a transaction
86//! let mut transaction = db.begin_transaction().await;
87//!
88//! User::insert_one(&db, User {id: 1, name: "Steve".to_string(), age: 3}, Some(&mut transaction)).await?;
89//! User::insert_one(&db, User {id: 2, name: "Johnny".to_string(), age: 3}, Some(&mut transaction)).await?;
90//! Comment::insert_many(
91//! &db,
92//! vec![
93//! Comment {
94//! user_id: 1,
95//! comment: "Hello".to_string(),
96//! },
97//! Comment {
98//! user_id: 1,
99//! comment: "Hi".to_string(),
100//! },
101//! ],
102//! Some(&mut transaction),
103//! )
104//! .await?;
105//!
106//! // Update the database
107//! // Define a struct to make updates consistent.
108//! #[derive(Serialize)]
109//! struct UpdateUser {
110//! name: Option<String>,
111//! age: Option<i32>
112//! }
113//! let query = Query::eq("name", "Steve");
114//! let update = UpdateUser { age: Some(5), name: None };
115//! User::update_one(&db, query, update, Some(&mut transaction)).await?;
116//!
117//! // Delete from the database
118//! let query = Query::eq("name", "Johnny");
119//! User::delete_one(&db, query, Some(&mut transaction)).await?;
120//!
121//! db.commit(&mut transaction).await?;
122//!
123//! Ok(())
124//! }
125//! ```
126//!
127//! ## Features
128//!
129//! - **ACID Compliant**: Deeb is an ACID compliant database. We get close as we can for a light weight JSON based DB.
130//! - **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.
131//! - **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.
132//! - **Transactions**: Perform multiple operations as a single unit — commit them all at once or roll them back if something fails.
133//! - **Querying**: Deeb supports querying, nested queries, and combination queries.
134//! - **Indexing**: Speed up query performance by creating indexes on single or multiple fields.
135//!
136//! ## Roadmap
137//!
138//! - [x] Basic CRUD Operations
139//! - [x] Transactions
140//! - [x] Indexing
141//! - [x] Querying
142//! - [ ] Migrations
143//! - [x] Benchmarks
144//! - [x] Associations
145//! - [x] Documentation
146//! - [x] Tests
147//! - [x] Examples
148//! - [ ] Logging
149//! - [ ] Error Handling
150//! - [ ] Improve Transactions - Should return updated object instead of Option<T>
151//! - [x] Implement traits and proc macros to streamline usage - `User.find_many(...)`
152//!
153//!
154//! ## Deeb
155//!
156//! ### Operations
157//!
158//! - `insert`: [Insert](deeb::Deeb::insert) a new document into the database
159//! - `find_one`: [Find](deeb::Deeb::find_one) a single document in the database
160//! - `find_many`: [Find multiple](deeb::Deeb::find_many) documents in the database
161//! - `update_one`: [Update a single](deeb::Deeb::update_one) document in the database
162//! - `update_many`: [Update multiple](deeb::Deeb::update_many) documents in the database
163//! - `delete_one`: [Delete a single](deeb::Deeb::delete_one) document in the database
164//! - `delete_many`: [Delete multiple](deeb::Deeb::delete_many) documents in the database
165//!
166//! ### Queries
167//!
168//! - `eq`: [Equal](database::query::Query::eq) - Find documents based on exact match.
169//! - `like`: [Like](database::query::Query::like) - Find documents based on like match.
170//! - `ne`: [Not Equal](database::query::Query::ne) - Find documents based on not equal match.
171//! - `gt`: [Greater Than](database::query::Query::gt) - Find documents based on greater than match.
172//! - `lt`: [Less Than](database::query::Query::lt) - Find documents based on less than match.
173//! - `gte`: [Greater Than or Equal](database::query::Query::gte) - Find documents based on greater than or equal match.
174//! - `lte`: [Less Than or Equal](database::query::Query::lte) - Find documents based on less than or equal match.
175//! - `and`: [And](database::query::Query::and) - Find documents based on multiple conditions.
176//! - `or`: [Or](database::query::Query::or) - Find documents based on multiple conditions.
177//! - `all`: [All](database::query::Query::all) - Return all documents.
178//! - `associated`: [Associated](database::query::Query::associated) - Find documents based on association.
179//!
180//! ### Transactions
181//!
182//! - `begin_transaction`: [Begin](deeb::Deeb::begin_transaction) a new transaction
183//! - `commit`: [Commit](deeb::Deeb::commit) a transaction
184//!
185//! ### Indexing
186//!
187//! - `add_index`: Add an index to an entity to improve query performance.
188//!
189//! ### Data Management
190//!
191//! - `add_key` : [Add a new key](deeb::Deeb::add_key) to every document in a collection
192//! - `drop_key` : [Drop a key](deeb::Deeb::drop_key) from every document in a collection
193
194mod deeb;
195
196pub use crate::deeb::Deeb;
197pub use deeb_core::{
198 database::{
199 find_many_options::{FindManyOptions, FindManyOrder, OrderDirection},
200 instance_name::InstanceName,
201 query::Query,
202 transaction::Transaction,
203 Database, DbResult, ExecutedValue, Operation,
204 },
205 entity::{Entity, EntityName},
206};
207pub use deeb_macros::Collection;