12 releases
0.3.5 | May 25, 2024 |
---|---|
0.3.3 | Oct 17, 2022 |
0.3.1 | Feb 14, 2022 |
0.3.0 | Aug 10, 2021 |
0.2.0 | Feb 15, 2021 |
#270 in Database interfaces
798 downloads per month
150KB
3K
SLoC
Mongo
A higher-level wrapper on top of the official bson & mongodb crates.
Overview
The mongod
crate is an unofficial higher-level wrapper that aims to make the bson & mongodb crates a little bit more rust-like.
Provides the following:
- builder style queries
- clients with async/non-async support
- derives for
Bson
&Mongo
to help with BSON type conversion and implentation of traits provided by this crate - strong opinions through the use of traits
Example
futures = "0.3"
mongod = { version = "0.3", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
use futures::stream::StreamExt;
use mongod::{Bson, Mongo};
use mongod::{AsFilter, AsUpdate, Collection, Comparator, Updates};
#[derive(Debug, Bson, Mongo)]
#[mongo(collection = "users", field, filter, update)]
pub struct User {
pub name: String,
pub age: Option<u32>,
}
#[tokio::main]
async fn main() {
// Create and async client
let client = mongod::Client::new();
// Insert a user into the users collection
let user = User { name: "foo".to_string(), age: None };
let oid = client.insert_one::<User>(user).await.unwrap();
println!("{:?}", oid);
// Fetch all users in the users collection
let mut cursor = client.find::<User, _>(None).await.unwrap();
while let Some(res) = cursor.next().await {
if let Ok((id, user)) = res {
println!("{} - {:?}", id, user);
}
}
// Update the user
let mut filter = User::filter();
filter.name = Some(Comparator::Eq("foo".to_owned()));
let mut update = User::update();
update.age = Some(Some(0));
let updates = Updates {
set: Some(update),
..Default::default()
};
let updated = client.update::<User, _, _>(filter, updates).await.unwrap();
println!("updated {} documents", updated);
// Delete all users
let deleted = client.delete::<User, _>(None).await.unwrap();
println!("delete {} documents", deleted);
}
Client
Async
The default client is async and provides convenience functions over those exposed by the mongodb driver.
Example: see above.
Blocking
Not everything should be async and for that reason a blocking client is provided that can be used at the same time as the async client.
mongod = { version = "0.3", features = ["blocking", "derive"] }
use mongod::{Bson, Mongo};
use mongod::{AsFilter, AsUpdate, Collection, Comparator, Updates};
#[derive(Debug, Bson, Mongo)]
#[mongo(collection = "users", field, filter, update)]
pub struct User {
pub name: String,
pub age: Option<u32>,
}
fn main() {
// Create and async client
let client = mongo::blocking::Client::new();
// Insert a user into the users collection
let user = User { name: "foo".to_string(), age: None };
let oid = client.insert_one::<User>(user).unwrap();
println!("{:?}", oid);
// Fetch all users in the users collection
let mut cursor = client.find::<User, _>(None).unwrap();
while let Some(res) = cursor.next() {
if let Ok((id, user)) = res {
println!("{} - {:?}", user);
}
}
// Update the user
let mut filter = User::filter();
filter.name = Some(Comparator::Eq("foo".to_owned()));
let mut update = User::update();
update.age = Some(Some(0));
let updates = Updates {
set: Some(update),
..Default::default()
};
let updated = client.update::<User, _, _>(filter, updates).unwrap();
println!("updated {} documents", updated);
// Delete all users
let deleted = client.delete::<User, _>(None).unwrap();
println!("delete {} documents", deleted);
}
Complex Queries
Sometimes the convenience queries provided on the client are not enough, the query builders can be used instead.
use mongod::Query;
...
let result = Query::insert::<User>::new()
.document_validation(false)
.ordered(false)
.query(&client, vec![user])
.await
.unwrap();
...
Serde
Sometimes there are reasons that implenting TryFrom
is just too difficult, but serde implentations already exist.
By tweaking the Mongo
derive it can be changed to be serde backed.
use mongod::Mongo;
#[derive(Debug, Mongo)]
#[mongo(bson = "serde", collection = "users", field, filter, update)]
pub struct User {
pub name: String,
pub age: Option<u32>,
}
...
Too Many Opinions
This library is too opinionated but I wanna use the derives...
Well as the derives are basically just fancy ways to convert rust types into BSON, they can be used without the mongod
clients.
Below is an example of the mongodb
client but using a mongod
derived user.
use mongod::{Bson, Mongo};
use mongod::Collection;
use mongod::db::Client;
#[derive(Debug, Bson, Mongo)]
#[mongo(collection = "users", field, filter, update)]
pub struct User {
pub name: String,
}
let client = Client::with_uri_str("mongodb://localhost:27017/").await.unwrap();
let db = client.database("db");
let users = db.collection("users");
let user = User { name: "foo".to_owned() };
let result = users.insert_one(user.into_document().unwrap(), None).unwrap();
TODO
- Add proc macro tests
- Not all features have been implented yet...
Dependencies
~26–38MB
~690K SLoC