Spark-ORM is a high-performance, open-source Object-Relational Mapping (ORM) library designed specifically for MongoDB in Rust. It seamlessly bridges Rust structs with MongoDB collections, effortlessly converting structs into models.
-
Derive Models: Effortlessly convert Rust structs into MongoDB models using the
Model
trait derivation. -
Custom Collection Names: Tailor collection names for your models with the
#[coll_name]
attribute. -
Memory Efficiency: Built for speed and memory efficiency, Spark-ORM offers a non-heap copy ORM solution for MongoDB.
-
Define your model by simply applying the
Model
attribute and setting the collection name withcoll_name
:#[Model(coll_name = "users")] #[derive(Serialize, Deserialize, Default, Debug)] struct User { age: u32, name: String, email: String, }
-
Connect to the database in one of two ways:
a. Establish a global connection:
Spark::global_connect("root", "123", "localhost", "6789", "rm_orm_db").await;
b. Or connect locally:
Spark::connect("root", "123", "localhost", "6789", "rm_orm_db").await;
For the global connection, Spark retains it throughout the program, accessible via:
Spark::get_db();
Instantiate the model:
let mut user = User::new_model(Some(&db));
OR you can use the global connection :
let mut user = User::new_model(None);
if you didn't set global connection , the new_model function will panic
Update attributes:
user.name = "Hossein".to_string();
user.age = 22;
Save to the database:
user.save().await.unwrap();
Find a model:
let mut user_model = User::new_model(Some(&db));
let mut sample = User::default ();
sample.name = "Hossein".to_string();
let founded = user_model.find_one(
sample,
None,
).await.unwrap();
println!("The founded object {:?} ", founded);
Update and save:
let mut user = User::new_model(Some(&db));
user.name = "Hossein".to_string();
user.email = "spark_orm_test".to_string();
user.save().await;
user.name = "Nothing".to_string();
user.save().await;
let db = get_db().await;
let user_model = User::new_model(Some(&db));
let updated = user_model.update(
doc! {
"name": "Hossein",
},
doc! {
"$set": {
"name": "Hossein 33"
}
},
None,
).await.unwrap();
println!("The Updated info {:?}", updated);
Delete a record:
let mut user = User::new_model(Some(&db));
user.delete().await;
Note: you can use the ?
instead of unwrap
The model trait adds _id , timestamps (created_at , updated_at , deleted_at) to your struct and fill automatically
Define index or unique attributes for struct fields:
#[Model(coll_name = "products")]
#[derive(Serialize, Deserialize, Default, Debug)]
struct Product {
#[index]
age: u32,
#[index]
name: String,
#[unique]
email: String,
}
These indexes are registered during the first initiation of Product.
you call set observer for some operations in model
to use the observer you just need to put observer
in Model
macro ex : #[Model(coll_name='users' , observer)]
and implement the Observer<T>
for your model , supported method are created , updated , deleted
#[Model(coll_name = "users", observer)]
#[derive(Serialize, Deserialize, Debug, Default)]
struct User {
name: String,
}
#[Model(coll_name = "persons", observer)]
#[derive(Serialize, Deserialize, Debug, Default)]
struct Person {
name: String,
}
impl Observer<User> for User {
async fn created(model: &mut Model<'_, User>) -> MongodbResult<()> {
let mut person_model = Person::new_model(None);
if model.name == "Hello".to_string() {
model.name = "Something".to_string();
model.save(None).await?;
}
person_model.name = "Naruto".to_string();
person_model.save(None).await?;
Ok(())
}
}
#[allow(clippy::assigning_clones)]
impl Observer<Person> for Person {
async fn created(model: &mut Model<'_, Person>) -> MongodbResult<()> {
let mut jobs = Jobs::new_model(None);
jobs.person.name = model.name.clone();
jobs.save(None).await?;
Ok(())
}
async fn updated(model: &mut Model<'_, Person>) -> MongodbResult<()> {
Ok(())
}
async fn deleted(model: &mut Model<'_, Person>) -> MongodbResult<()> {
Ok(())
}
}