Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/withsecurelabs/mongo-rs
A higher-level wrapper on top of the official bson & mongodb crates.
https://github.com/withsecurelabs/mongo-rs
countercept mongodb rust
Last synced: about 7 hours ago
JSON representation
A higher-level wrapper on top of the official bson & mongodb crates.
- Host: GitHub
- URL: https://github.com/withsecurelabs/mongo-rs
- Owner: WithSecureLabs
- License: mit
- Created: 2020-12-21T18:09:34.000Z (almost 4 years ago)
- Default Branch: master
- Last Pushed: 2024-04-23T15:21:58.000Z (7 months ago)
- Last Synced: 2024-05-21T11:41:39.472Z (6 months ago)
- Topics: countercept, mongodb, rust
- Language: Rust
- Homepage:
- Size: 96.7 KB
- Stars: 15
- Watchers: 5
- Forks: 5
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Mongo
[![crates.io](https://img.shields.io/crates/v/mongod.svg)](https://crates.io/crates/mongod)
[![Documentation](https://docs.rs/mongod/badge.svg)](https://docs.rs/mongod)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
```toml
futures = "0.3"
mongod = { version = "0.3", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
``````rust
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,
}#[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).await.unwrap();
println!("{:?}", oid);// Fetch all users in the users collection
let mut cursor = client.find::(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::(filter, updates).await.unwrap();
println!("updated {} documents", updated);// Delete all users
let deleted = client.delete::(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.
```toml
mongod = { version = "0.3", features = ["blocking", "derive"] }
``````rust
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,
}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).unwrap();
println!("{:?}", oid);// Fetch all users in the users collection
let mut cursor = client.find::(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::(filter, updates).unwrap();
println!("updated {} documents", updated);// Delete all users
let deleted = client.delete::(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.
```rust
use mongod::Query;...
let result = Query::insert::::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.```rust
use mongod::Mongo;#[derive(Debug, Mongo)]
#[mongo(bson = "serde", collection = "users", field, filter, update)]
pub struct User {
pub name: String,
pub age: Option,
}...
```## 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.```rust
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...